home *** CD-ROM | disk | FTP | other *** search
/ The Games Machine 80 / XENIATGM80.iso / Goodies / Blood 2 / Source / data.z / BloodClientShell.cpp < prev    next >
C/C++ Source or Header  |  1999-04-02  |  243KB  |  9,406 lines

  1. //----------------------------------------------------------
  2. //
  3. // MODULE  : BloodClientShell.cpp
  4. //
  5. // PURPOSE : Blood 2 Client shell
  6. //
  7. // CREATED : 9/21/97
  8. //
  9. //----------------------------------------------------------
  10.  
  11.  
  12. // includes...
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #include "BloodClientShell.h"
  16. #include "ViewWeapon.h"
  17. #include "Commands.h"
  18. #include "VKDefs.h"
  19. #include "ClientRes.h"
  20. #include "SfxMsgIds.h"
  21. #include "ClientUtilities.h"
  22. #include "LoadSave.h"
  23. #include "VolumeBrushFX.h"
  24. #include "CameraFX.h"
  25. #include "client_physics.h"
  26. #include "NetStart.h"
  27. #include "TheVoice.h"
  28. #include "WinUtil.h"
  29. #include "ClientRes.h"
  30. #include "LoadScreenData.h"
  31. #include "Splash.h"
  32. #include "MoveMgr.h"
  33. #include "WeaponDefs.h"
  34. #include "GameWeapons.h"
  35. #include "SoundTypes.h"
  36. #include "physics_lt.h"
  37.  
  38. PhysicsState      g_normalPhysicsState;
  39. PhysicsState      g_waterPhysicsState;
  40.  
  41. //#define FLAG_BASECHARACTER    1
  42.  
  43. // defines...
  44.  
  45. #define BOBV_WALKING    24.0f
  46. #define BOBH_WALKING    16.0f
  47. #define SWAYV_WALKING    32.0f
  48. #define SWAYH_WALKING    80.0f
  49.  
  50. #define BOBV_CRAWLING    24.0f
  51. #define BOBH_CRAWLING    16.0f
  52. #define SWAYV_CRAWLING    16.0f
  53. #define SWAYH_CRAWLING    40.0f
  54.  
  55. #define FOV_NORMAL        90.0f
  56. #define FOV_SEEING_EYE    120.0f
  57. #define FOV_ZOOMED        12.5f
  58.  
  59. #define MOVIE_STARTLITH        1
  60. #define MOVIE_PLAYINGLITH    2
  61. #define MOVIE_STARTGTI        3
  62. #define MOVIE_PLAYINGGTI    4
  63. #define MOVIE_STARTINTRO    5
  64. #define MOVIE_PLAYINGINTRO    6
  65. #define MOVIE_FINISHED        7
  66.  
  67. #define min(a,b)    (a < b ? a : b)
  68. #define max(a,b)    (a > b ? a : b)
  69.  
  70. #define SOUND_REVERB_UPDATE_PERIOD        0.33f
  71. #define PLAYER_MULTI_UPDATE_TIMER        0.14f
  72.  
  73. #define    MSG_SOUND_STRING    "sounds\\events\\woodclank2a.wav"
  74.  
  75.  
  76. // Guids...
  77.  
  78. #ifdef _ADDON
  79.  
  80. DGUID BLOOD2GUID = { /* Add-On */ 
  81.     0xc13e628, 0x418c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x18, 0xa9, 0x42
  82. };
  83.  
  84. #else
  85.  
  86. DGUID BLOOD2GUID = { /* 0C13E629-419C-11D2-860A-00609719A842 */
  87.     0xc13e629, 0x419c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x19, 0xa8, 0x42
  88. };
  89.  
  90. #endif
  91.  
  92.  
  93. // Misc...
  94.  
  95. char    msgbuf[513];
  96.  
  97. DBOOL    g_bAborting                = DFALSE;
  98. DBOOL    g_bIsHost                  = DFALSE;
  99. DBOOL    g_bLevelChange3rdPersonCam = DFALSE;
  100. DBOOL    g_bLevelChangeNoUpdate     = DFALSE;
  101. DBOOL    g_bPlayerInvReset          = DFALSE;
  102.  
  103. DFLOAT    g_fPlayerUpdateTimer       = 0.0f;
  104.  
  105. #ifdef _ADDON
  106.  
  107. static char *s_szCheerSounds[] =
  108. {
  109.     "sounds_ao\\events\\cheer1.wav",
  110.     "sounds_ao\\events\\cheer2.wav"
  111. };
  112. #define NUMCHEERSOUNDS  ( sizeof( s_szCheerSounds ) / sizeof( s_szCheerSounds[0] ))
  113.  
  114. static char *s_szBooSounds[] =
  115. {
  116.     "sounds_ao\\events\\boo1.wav",
  117.     "sounds_ao\\events\\boo2.wav",
  118.     "sounds_ao\\events\\boo3.wav"
  119. };
  120. #define NUMBOOSOUNDS  ( sizeof( s_szBooSounds ) / sizeof( s_szBooSounds[0] ))
  121.  
  122. #endif // _ADDON
  123.  
  124.  
  125.  
  126. // Global pointer to the client shell..
  127. CBloodClientShell    *g_pBloodClientShell = DNULL;
  128.  
  129. // Prototypes..
  130. DBOOL ConnectToTcpIpAddress(CClientDE* pClientDE, char* sAddress);
  131.  
  132. // Setup..
  133.  
  134. SETUP_CLIENTSHELL();
  135.  
  136. ClientShellDE* CreateClientShell(ClientDE *pClientDE)
  137. {
  138.     g_pClientDE = pClientDE;
  139.     return (ClientShellDE*)(new CBloodClientShell);
  140. }
  141.  
  142. void DeleteClientShell(ClientShellDE *pInputShell)
  143. {
  144.     if (pInputShell)
  145.     {
  146.         delete ((CBloodClientShell*)pInputShell);
  147.     }
  148. }
  149.  
  150. void CShell_GetConsoleString(char* sKey, char* sDest, char* sDefault)
  151. {
  152.     if (g_pClientDE)
  153.     {
  154.         HCONSOLEVAR hVar = g_pClientDE->GetConsoleVar(sKey);
  155.         if (hVar)
  156.         {
  157.             char* sValue = g_pClientDE->GetVarValueString(hVar);
  158.             if (sValue)
  159.             {
  160.                 strcpy(sDest, sValue);
  161.                 return;
  162.             }
  163.         }
  164.     }
  165.  
  166.     strcpy(sDest, sDefault);
  167. }
  168.  
  169. static DBOOL LoadLeakFile(ClientDE *pClientDE, char *pFilename);
  170.  
  171. void LeakFileFn(int argc, char **argv)
  172. {
  173.     if (argc < 0)
  174.     {
  175.         g_pBloodClientShell->GetClientDE()->CPrint("LeakFile <filename>");
  176.         return;
  177.     }
  178.  
  179.     if (LoadLeakFile(g_pBloodClientShell->GetClientDE(), argv[0]))
  180.     {
  181.         g_pBloodClientShell->GetClientDE()->CPrint("Leak file %s loaded successfully!", argv[0]);
  182.     }
  183.     else
  184.     {
  185.         g_pBloodClientShell->GetClientDE()->CPrint("Unable to load leak file %s", argv[0]);
  186.     }
  187. }
  188.  
  189. void ConnectFn(int argc, char **argv)
  190. {
  191.     if (argc <= 0)
  192.     {
  193.         g_pBloodClientShell->GetClientDE()->CPrint("Connect <tcpip address> (use '*' for local net)");
  194.         return;
  195.     }
  196.  
  197.     ConnectToTcpIpAddress(g_pBloodClientShell->GetClientDE(), argv[0]);
  198. }
  199.  
  200. void NextLevelFn(int argc, char **argv)
  201. {
  202.     if (g_bIsHost)
  203.     {
  204.         ClientDE *pClientDE;
  205.         HMESSAGEWRITE hWrite;
  206.  
  207.         pClientDE = g_pBloodClientShell->GetClientDE();
  208.         hWrite = pClientDE->StartMessage(CMSG_NEXTLEVEL);
  209.         pClientDE->EndMessage(hWrite);
  210.     }
  211.     else
  212.     {
  213.         g_pBloodClientShell->GetClientDE()->CPrint("Only the host can change levels");
  214.     }
  215. }
  216.  
  217. void LoadLevelFn(int argc, char **argv)
  218. {
  219.     if (argc >= 1 && argv[0])
  220.     {
  221.         g_pBloodClientShell->StartNewGame(argv[0]);
  222.     }
  223.     else
  224.     {
  225.         g_pBloodClientShell->GetClientDE()->CPrint("Usage: load <level-name>");
  226.     }
  227. }
  228.  
  229. void CBloodClientShell::StartNewGame(char *pszWorld)
  230. {
  231.     if (!pszWorld) return;
  232.  
  233.     if (m_bInWorld)
  234.     {
  235.         StartNewWorld(pszWorld, m_nGameType, LOADTYPE_NEW_LEVEL);
  236.     }
  237.     else
  238.     {
  239.         StartNewGame(pszWorld, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM);
  240.         m_bFirstWorld = DTRUE;
  241.     }
  242. }
  243.  
  244. void FragSelfFn(int argc, char **argv)
  245. {
  246.     ClientDE *pClientDE;
  247.     HMESSAGEWRITE hWrite;
  248.  
  249.     pClientDE = g_pBloodClientShell->GetClientDE();
  250.     hWrite = pClientDE->StartMessage(CMSG_FRAGSELF);
  251.     pClientDE->EndMessage(hWrite);
  252. }
  253.  
  254. void InitSoundFn(int argc, char **argv)
  255. {
  256.     if( g_pBloodClientShell )
  257.         g_pBloodClientShell->InitSound( );
  258. }
  259.  
  260.  
  261. /*
  262. // --------------------------------------------------------------------------- //
  263. //
  264. //    ROUTINE:    AuraModelHook
  265. //
  266. //    PURPOSE:    Special Rendering Code for Aura spell
  267. //
  268. // --------------------------------------------------------------------------- //
  269.  
  270. void AuraModelHook (struct ModelHookData_t *pData, void *pUser)
  271. {
  272.     CClientDE* pClientDE = (CClientDE*) pUser;
  273.     if (!pClientDE ) return;
  274.     
  275.     DDWORD nUserFlags = 0;
  276.     pClientDE->GetObjectUserFlags (pData->m_hObject, &nUserFlags);
  277.     if (nUserFlags & FLAG_BASECHARACTER)
  278.     {
  279.         pData->m_Flags &= ~MHF_USETEXTURE;
  280.         if (pData->m_LightAdd)
  281.         {
  282.             VEC_SET (*pData->m_LightAdd, 255.0f, 255.0f, 255.0f);
  283.         }
  284.     }
  285. }
  286. */
  287.  
  288. // --------------------------------------------------------------------------- //
  289. //
  290. //    ROUTINE:    DefaultModelHook
  291. //
  292. //    PURPOSE:    Default model hook function
  293. //
  294. // --------------------------------------------------------------------------- //
  295.  
  296. void DefaultModelHook (struct ModelHookData_t *pData, void *pUser)
  297. {
  298.     DDWORD nUserFlags;
  299.     DFLOAT fGlowValue, fGlowFactor;
  300.  
  301.     g_pClientDE->GetObjectUserFlags( pData->m_hObject, &nUserFlags );
  302.  
  303.     if( g_pBloodClientShell->NightGogglesActive( ) && nUserFlags & USERFLG_NIGHTGOGGLESGLOW )
  304.     {
  305.         pData->m_Flags &= ~MHF_USETEXTURE;
  306.         if (pData->m_LightAdd)
  307.         {
  308.             VEC_SET (*pData->m_LightAdd, 0.0f, 255.0f, 0.0f);
  309.         }
  310.     }
  311.     else if( nUserFlags & USRFLG_GLOW )
  312.     {
  313.         if( pData->m_LightAdd )
  314.         {
  315.             // Cycle the glow with a period of 2 seconds...
  316.             fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE / 2.0f );
  317.             fGlowValue = 128.0f + 128.0f * fGlowFactor;
  318.             fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f );
  319.             VEC_SET( *pData->m_LightAdd, fGlowValue, fGlowValue, fGlowValue );
  320.         }
  321.     }
  322.     // Glow red for anger
  323.     else if (nUserFlags & USRFLG_ANGERGLOW)    
  324.     {
  325.         if( pData->m_LightAdd )
  326.         {
  327.             // Cycle the glow with a period of 0.5 seconds...
  328.             fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE * 6.0f );
  329.             fGlowValue = 192.0f + 64.0f * fGlowFactor;
  330.             fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f );
  331.             VEC_SET( *pData->m_LightAdd, fGlowValue, 255.0 - fGlowValue, 255.0 - fGlowValue );
  332.         }
  333.     }
  334.     // Glow green for willpower
  335.     else if (nUserFlags & USRFLG_WILLPOWERGLOW)
  336.     {
  337.         if( pData->m_LightAdd )
  338.         {
  339.             // Cycle the glow with a period of 0.5 seconds...
  340.             fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE * 6.0f );
  341.             fGlowValue = 192.0f + 64.0f * fGlowFactor;
  342.             fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f );
  343.             VEC_SET( *pData->m_LightAdd, 255.0 - fGlowValue, fGlowValue, 255.0 - fGlowValue );
  344.         }
  345.     }
  346. }
  347.  
  348. // ----------------------------------------------------------------------- //
  349. //
  350. //    ROUTINE:    CBloodClientShell::CBloodClientShell()
  351. //
  352. //    PURPOSE:    constructor
  353. //
  354. // ----------------------------------------------------------------------- //
  355.  
  356. CBloodClientShell::CBloodClientShell()
  357. {
  358.     m_pMoveMgr                = DNULL;
  359.     m_hCamera                = NULL;
  360.     m_fPitch = m_fYaw =    cdata.fPitch = cdata.fYaw = 0.0f;
  361.     for (int i=0;i<CLIENTWEAPONSLOTS;i++)
  362.     {
  363.         m_abyWeaponID[i]    = WEAP_NONE;
  364.         m_abyLWeaponID[i]    = WEAP_NONE;
  365.     }
  366.     m_pWeapon                = DNULL;
  367.     m_pLWeapon                = DNULL;
  368.  
  369.     m_hWeapHandObj            = DNULL;
  370.     m_hLWeapHandObj            = DNULL;
  371.  
  372.     m_nGameState            = GS_NONE;        
  373.  
  374.     m_bInWorld                = DFALSE;
  375.     m_hCrosshair            = NULL;
  376.     m_bShowCrosshair        = DFALSE;
  377.     m_nCrosshair            = 0;
  378.     m_nLastCrosshair        = 0;
  379.     m_nCrosshairOriginalNum = 0;
  380.     m_bCrosshairOriginallyOn = 0;
  381.     m_cxCrosshair = m_cyCrosshair = 0;
  382.     m_DefFovX                = FOV_NORMAL;
  383.     m_fovYScale                = 0.80f;
  384.     m_fovX                    = 0;
  385.     m_fovY                    = 0;
  386.  
  387.     m_fCantIncrement        = 0.006f; // in radians (.25 degrees)
  388.     m_fCantMaxDist            = 0.036f; // in radians (2.0 degrees)
  389.     m_fCamCant                = 0.0f;
  390.  
  391.     cdata.byFlags            = 0;
  392.  
  393.     // Set up default attributes
  394.     _mbscpy((unsigned char*)m_Config.szName, (const unsigned char*)"Player");
  395.     m_Config.nCharacter        = CHARACTER_CALEB;
  396.     m_Config.nSkin            = MULTIPLAY_SKIN_NORMAL;
  397.     m_Config.nStrength        = 5;
  398.     m_Config.nSpeed            = 3;
  399.     m_Config.nResistance    = 3;
  400.     m_Config.nMagic            = 1;
  401.     m_bDrawStatusBar        = DTRUE;
  402.     m_bDrawFragBar            = DFALSE;
  403.  
  404.     m_bRenderCamera            = DFALSE;
  405.     m_pExternalCamera        = DNULL;
  406.     m_hSeeingEyeObj            = DNULL;
  407.     m_hOrbObj                = DNULL;
  408.     m_hLastOrbObj            = DNULL;
  409.  
  410.     m_bBurn                    = DFALSE;
  411.     m_bBlind                = DFALSE;
  412.     m_bFadeIn                = DFALSE;
  413.     m_bFadeOut                = DFALSE;
  414.     m_fFadeVal                = 0.0f;
  415.     m_fBurnTime                = 0.0f;
  416.     m_fBlindTime            = 0.0f;
  417.  
  418.     m_hstrTitle                = DNULL;
  419.     m_hstrLoadScreen        = DNULL;
  420.     m_nLoadScreenID            = 0;
  421.  
  422.     // Advanced options
  423.     m_bAdvancedDisableMusic            = DFALSE;
  424.     m_bAdvancedDisableSound            = DFALSE;
  425.     m_bAdvancedDisableMovies        = DFALSE;
  426.     m_bAdvancedDisableJoystick        = DFALSE;
  427.     m_bAdvancedEnableOptSurf        = DFALSE;
  428.     m_bAdvancedDisableLightMap        = DFALSE;
  429.     m_bAdvancedEnableTripBuf        = DFALSE;
  430.     m_bAdvancedDisableDx6Cmds        = DFALSE;
  431.     m_bAdvancedEnableTJuncs            = DFALSE;
  432.     m_bAdvancedDisableFog            = DFALSE;
  433.     m_bAdvancedDisableLines            = DFALSE;
  434.     m_bAdvancedDisableModelFB        = DFALSE;
  435.     m_bAdvancedEnablePixelDoubling    = DFALSE;
  436.     m_bAdvancedEnableMultiTexturing = DFALSE;
  437.  
  438.     // Container init
  439.     m_hContainerSound        = DNULL;
  440.     m_eCurContainerCode        = CC_NOTHING;
  441.  
  442.     m_fContainerStartTime    = -1.0f;
  443.     m_fFovXFXDir            = 1.0f;
  444.     m_fLastTime                = 0.0f;
  445.  
  446.     m_fRotDir                = 1.0f;
  447.     m_fMaxRot                = 0.55f;
  448.  
  449.     m_bFirstUpdate            = DFALSE;
  450.  
  451.     m_hLoadingScreen        = DNULL;
  452.     m_fLoadingFadeTime        = 0.0f;
  453.     m_bLoadingFadeUp        = DTRUE;
  454.     m_bPlayedWaitingSound    = DFALSE;
  455.  
  456.     m_bHandledStartup        = DFALSE;
  457.     m_bFirstWorld            = DTRUE;
  458.  
  459.     m_SavedGameInfo.LoadInfo();
  460.  
  461.     g_pBloodClientShell        = this;
  462.     m_bDemoPlayback            = DFALSE;
  463.  
  464.     m_bShiftState            = DFALSE;
  465.     m_bRollCredits          = DFALSE;
  466.  
  467.     _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)"");
  468.  
  469.     m_pCreature = DNULL;
  470.  
  471. #ifdef BRANDED
  472.     m_fBrandCounter            = 45.0f;
  473.     m_hBrandSurface            = DNULL;
  474. #endif
  475.  
  476.     m_bIgnoreKeyboardMessage=DFALSE;
  477.     g_bAborting = DFALSE;
  478.  
  479.     m_hCurrentItemName = DNULL;
  480.     m_hCurrentItemIcon = DNULL;
  481.     m_hCurrentItemIconH = DNULL;
  482.     m_nCurrentItemCharge = 0;
  483.     m_hPrevItemIcon = DNULL;
  484.     m_nPrevItemCharge = 0;
  485.     m_hNextItemIcon = DNULL;
  486.     m_nNextItemCharge = 0;
  487.  
  488.     m_nGlobalDetail = DETAIL_LOW;
  489.  
  490.     m_bMouseInvertYAxis = DFALSE;
  491.     m_bUseJoystick = DFALSE;
  492.     m_bMouseLook = DTRUE;
  493.     m_bLookSpring = DFALSE;
  494.  
  495.     m_bNightGogglesActive = DFALSE;
  496.     m_hNightGogglesSound = DNULL;
  497.     m_hTheEyeLoopingSound = DNULL;
  498.  
  499.     m_bBinocularsActive = DFALSE;
  500.  
  501.     m_bPaused = DFALSE;
  502.     m_bInMessageBox = DFALSE;
  503.  
  504.     m_eMusicLevel            = CMusic::MUSICLEVEL_SILENCE;
  505.  
  506.     // Camera stuff...
  507.     m_fOffsetY = 0.0f;
  508.     m_fOffsetX = 0.0f;
  509.     m_fOffsetRot = 0.0f;
  510.     ROT_INIT(m_Rotation);
  511.  
  512.     m_hstrObjectivesText = DNULL;
  513.     m_hstrObjectivesTitle = DNULL;
  514.  
  515.     m_dwAmmo = 0;
  516.     m_dwAltAmmo = 0;
  517.  
  518.     m_hCtfCapturedString1 = DNULL;
  519.     m_hCtfCapturedString2 = DNULL;
  520.  
  521. #ifdef _ADDON
  522.     m_hSoccerGoalString1 = DNULL;
  523.     m_hSoccerGoalString2 = DNULL;
  524. #endif // _ADDON
  525.  
  526.     m_nLastLoadType = LOADTYPE_NEW_GAME;
  527.  
  528.     m_bUseReverb = DFALSE;
  529.     m_fReverbLevel = 0.0f;
  530.     VEC_INIT( m_vLastReverbPos );
  531.  
  532.     m_bNetFriendlyFire   = DFALSE;
  533.     m_bNetNegTeamFrags   = DFALSE;
  534.     m_bNetOnlyFlagScores = DFALSE;
  535.     m_bNetOnlyGoalScores = DFALSE;
  536.  
  537.     m_nTrapped = 0;
  538. }
  539.  
  540.  
  541. // ----------------------------------------------------------------------- //
  542. //
  543. //    ROUTINE:    CBloodClientShell::~CBloodClientShell()
  544. //
  545. //    PURPOSE:    Destruction
  546. //
  547. // ----------------------------------------------------------------------- //
  548.             
  549. CBloodClientShell::~CBloodClientShell()
  550. {
  551.     CClientDE* pClientDE = GetClientDE();
  552.  
  553.  
  554.     if (m_pMoveMgr)
  555.     {
  556.         delete m_pMoveMgr;
  557.         m_pMoveMgr = DNULL;
  558.     }
  559.  
  560.     if (m_pWeapon) delete m_pWeapon;
  561.     if (m_pLWeapon) delete m_pLWeapon;
  562.  
  563.     g_pBloodClientShell = DNULL;
  564.     if( m_hCurrentItemName )
  565.         pClientDE->FreeString( m_hCurrentItemName );
  566.     if( m_hCurrentItemIcon )
  567.         pClientDE->FreeString( m_hCurrentItemIcon );
  568.     if( m_hCurrentItemIconH )
  569.         pClientDE->FreeString( m_hCurrentItemIconH );
  570.     if( m_hPrevItemIcon )
  571.         pClientDE->FreeString( m_hPrevItemIcon );
  572.     if( m_hNextItemIcon )
  573.         pClientDE->FreeString( m_hNextItemIcon );
  574.  
  575.     if( m_hNightGogglesSound )
  576.     {
  577.         g_pClientDE->KillSound( m_hNightGogglesSound );
  578.     }
  579.  
  580.     if( m_hTheEyeLoopingSound )
  581.     {
  582.         g_pClientDE->KillSound( m_hTheEyeLoopingSound );
  583.     }
  584.  
  585.     if( m_hContainerSound)
  586.     {
  587.         g_pClientDE->KillSound( m_hContainerSound );
  588.     }
  589.  
  590.     if( m_hstrTitle )
  591.         g_pClientDE->FreeString( m_hstrTitle );
  592.     if( m_hstrLoadScreen )
  593.         g_pClientDE->FreeString( m_hstrLoadScreen );
  594.     if( m_hstrObjectivesText )
  595.         g_pClientDE->FreeString( m_hstrObjectivesText );
  596.     if( m_hstrObjectivesTitle )
  597.         g_pClientDE->FreeString( m_hstrObjectivesTitle );
  598.  
  599.     if (m_hCtfCapturedString1)
  600.         g_pClientDE->FreeString(m_hCtfCapturedString1);
  601.     if (m_hCtfCapturedString2)
  602.         g_pClientDE->FreeString(m_hCtfCapturedString2);
  603.  
  604. #ifdef _ADDON
  605.     if (m_hSoccerGoalString1)
  606.         g_pClientDE->FreeString(m_hSoccerGoalString1);
  607.     if (m_hSoccerGoalString2)
  608.         g_pClientDE->FreeString(m_hSoccerGoalString2);
  609. #endif // _ADDON
  610. }    
  611.  
  612.  
  613.  
  614. // ----------------------------------------------------------------------- //
  615. //
  616. //    ROUTINE:    CBloodClientShell::InitSound
  617. //
  618. //    PURPOSE:    Initialize the sounds
  619. //
  620. // ----------------------------------------------------------------------- //
  621.  
  622. DRESULT CBloodClientShell::InitSound()
  623. {
  624.     Sound3DProvider *pSound3DProviderList, *pSound3DProvider;
  625.     InitSoundInfo soundInfo;
  626.     ReverbProperties reverbProperties;
  627.     HCONSOLEVAR hVar;
  628.     DDWORD dwProviderID;
  629.     char sz3dSoundProviderName[_MAX_PATH + 1];
  630.     DRESULT res;
  631.  
  632.     CClientDE* pClientDE = GetClientDE();
  633.     if( !pClientDE )
  634.         return LT_ERROR;
  635.  
  636.     INITSOUNDINFO_INIT(soundInfo);
  637.  
  638.     // Reload the sounds if there are any
  639.     soundInfo.m_dwFlags                = INITSOUNDINFOFLAG_RELOADSOUNDS;
  640.  
  641.     // Get the 3d sound provider id.
  642.     hVar = pClientDE->GetConsoleVar( "3DSoundProvider" );
  643.     if( hVar )
  644.     {
  645.         dwProviderID = ( DDWORD )pClientDE->GetVarValueFloat( hVar );
  646.     }
  647.     else
  648.         dwProviderID = SOUND3DPROVIDERID_NONE;
  649.  
  650.     // Can also be set by provider name, in which case the id will be set to UNKNOWN.
  651.     if( dwProviderID == SOUND3DPROVIDERID_NONE || dwProviderID == SOUND3DPROVIDERID_UNKNOWN )
  652.     {
  653.         sz3dSoundProviderName[0] = 0;
  654.         hVar = pClientDE->GetConsoleVar( "3DSoundProviderName" );
  655.         if( hVar )
  656.         {
  657.             SAFE_STRCPY( sz3dSoundProviderName, pClientDE->GetVarValueString( hVar ));
  658.             dwProviderID = SOUND3DPROVIDERID_UNKNOWN;
  659.         }
  660.     }
  661.  
  662.     // See if the provider exists.
  663.     if( dwProviderID != SOUND3DPROVIDERID_NONE )
  664.     {
  665.         pClientDE->GetSound3DProviderLists( pSound3DProviderList, DFALSE );
  666.         if( !pSound3DProviderList )
  667.             return LT_NO3DSOUNDPROVIDER;
  668.  
  669.         pSound3DProvider = pSound3DProviderList;
  670.         while( pSound3DProvider )
  671.         {
  672.             // If the provider is selected by name, then compare the names.
  673.             if( dwProviderID == SOUND3DPROVIDERID_UNKNOWN )
  674.             {
  675.                 if( _mbscmp(( const unsigned char * )sz3dSoundProviderName, ( const unsigned char * )pSound3DProvider->m_szProvider ) == 0 )
  676.                     break;
  677.             }
  678.             // Or compare by the id's.
  679.             else if( pSound3DProvider->m_dwProviderID == dwProviderID )
  680.                 break;
  681.  
  682.             // Not this one, try next one.
  683.             pSound3DProvider = pSound3DProvider->m_pNextProvider;
  684.         }
  685.  
  686.         // Check if we found one.
  687.         if( pSound3DProvider )
  688.         {
  689.             // Use this provider.
  690.             SAFE_STRCPY( soundInfo.m_sz3DProvider, pSound3DProvider->m_szProvider );
  691.  
  692.             // Get the maximum number of 3d voices to use.
  693.             hVar = pClientDE->GetConsoleVar( "Max3DVoices" );
  694.             if( hVar )
  695.             {
  696.                 soundInfo.m_nNum3DVoices = ( DBYTE )g_pClientDE->GetVarValueFloat( hVar );
  697.             }
  698.             else
  699.                 soundInfo.m_nNum3DVoices = 16;
  700.         }
  701.  
  702.         pClientDE->ReleaseSound3DProviderList( pSound3DProviderList );
  703.     }
  704.  
  705.     // Get the maximum number of sw voices to use.
  706.     hVar = pClientDE->GetConsoleVar( "MaxSWVoices" );
  707.     if( hVar )
  708.     {
  709.         soundInfo.m_nNumSWVoices = ( DBYTE )g_pClientDE->GetVarValueFloat( hVar );
  710.     }
  711.     else
  712.         soundInfo.m_nNumSWVoices = 32;
  713.  
  714.     soundInfo.m_nSampleRate            = 22050;
  715.     soundInfo.m_nBitsPerSample        = 16;
  716.     if ((hVar = pClientDE->GetConsoleVar("soundvolume")))
  717.     {
  718.         soundInfo.m_nVolume = (unsigned short)(pClientDE->GetVarValueFloat(hVar));
  719.     }        
  720.     
  721.     DBOOL b8bitOnly = DFALSE;
  722.     hVar = pClientDE->GetConsoleVar("sound16bit");
  723.     if (hVar)
  724.     {
  725.         b8bitOnly = (pClientDE->GetVarValueFloat(hVar) == 0.0f) ? DTRUE : DFALSE;
  726.     }        
  727.     if( b8bitOnly )
  728.         soundInfo.m_dwFlags |= INITSOUNDINFOFLAG_CONVERT16TO8;
  729.  
  730.  
  731.     DFLOAT fMinStreamSoundTime = 0.5f;
  732.     hVar = pClientDE->GetConsoleVar ("MinStreamTime");
  733.     if (hVar)
  734.     {
  735.         fMinStreamSoundTime = pClientDE->GetVarValueFloat (hVar);
  736.         fMinStreamSoundTime = (fMinStreamSoundTime < 0.2f ? 0.2f :
  737.                                (fMinStreamSoundTime > 1.5f ? 1.5f : fMinStreamSoundTime));
  738.     }
  739.     soundInfo.m_fMinStreamTime = fMinStreamSoundTime;
  740.     soundInfo.m_fDistanceFactor = 1.0f / 64.0f;
  741.  
  742.     // Go initialize the sounds.
  743.     m_bUseReverb = DFALSE;
  744.     if(( res = pClientDE->InitSound(&soundInfo)) == LT_OK )
  745.     {
  746.         if( soundInfo.m_dwResults & INITSOUNDINFORESULTS_REVERB )
  747.         {
  748.             m_bUseReverb = DTRUE;
  749.         }
  750.  
  751.         hVar = pClientDE->GetConsoleVar( "ReverbLevel" );
  752.         if( hVar )
  753.         {
  754.             m_fReverbLevel = g_pClientDE->GetVarValueFloat( hVar );
  755.         }
  756.         else
  757.             m_fReverbLevel = 1.0f;
  758.  
  759.         reverbProperties.m_dwParams = REVERBPARAM_VOLUME;
  760.         reverbProperties.m_fVolume = m_fReverbLevel;
  761.         pClientDE->SetReverbProperties( &reverbProperties );
  762.     }
  763.  
  764.     return res;
  765. }
  766.  
  767.  
  768. // ----------------------------------------------------------------------- //
  769. //
  770. //    ROUTINE:    CBloodClientShell::CSPrint
  771. //
  772. //    PURPOSE:    Displays a line of text on the client
  773. //
  774. // ----------------------------------------------------------------------- //
  775.  
  776. void CBloodClientShell::CSPrint (char* msg, ...)
  777. {
  778.     CClientDE* pClientDE = GetClientDE();
  779.  
  780.     // parse the message
  781.     char pMsg[256];
  782.     va_list marker;
  783.     va_start (marker, msg);
  784.     int nSuccess = vsprintf (pMsg, msg, marker);
  785.     va_end (marker);
  786.  
  787.     if (nSuccess < 0) return;
  788.      
  789.     // now display the message
  790.     m_MessageMgr.AddLine(pMsg);
  791.     pClientDE->CPrint(pMsg);
  792. }
  793.  
  794. void CBloodClientShell::CSPrint(int nStringID)
  795. {
  796.     CClientDE* pClientDE = GetClientDE();
  797.     if (!pClientDE) return;
  798.  
  799.     HSTRING hString = pClientDE->FormatString(nStringID);
  800.     if (!hString) return;
  801.  
  802.     CSPrint(pClientDE->GetStringData(hString));
  803.  
  804.     pClientDE->FreeString(hString);
  805. }
  806.  
  807. void CBloodClientShell::CSPrint2(char* msg)
  808. {
  809.     CClientDE* pClientDE = GetClientDE();
  810.     if (!pClientDE) return;
  811.  
  812.     m_MessageMgr.AddLine(msg);
  813.     pClientDE->CPrint(msg);
  814. }
  815.  
  816.  
  817. // --------------------------------------------------------------------------- //
  818. //
  819. //    ROUTINE:    CBloodClientShell::OnEvent()
  820. //
  821. //    PURPOSE:    Engine event handler
  822. //
  823. // --------------------------------------------------------------------------- //
  824.  
  825. void CBloodClientShell::OnEvent(DDWORD dwEventID, DDWORD dwParam)
  826. {
  827.     // Handle any events we want to deal with...
  828.  
  829.     switch (dwEventID)
  830.     {
  831.         case LTEVENT_DISCONNECT:
  832.         {
  833.             if (!g_bIsHost)
  834.             {
  835.                 CSPrint(IDS_SERVERDISCONNECT);
  836.                 PlaySound(MSG_SOUND_STRING);
  837.             }
  838.             break;
  839.         }
  840.     }
  841.  
  842.  
  843.     // Let the base class handle the even too...
  844.  
  845.     CClientShellDE::OnEvent(dwEventID, dwParam);
  846. }
  847.  
  848.  
  849. // --------------------------------------------------------------------------- //
  850. //
  851. //    ROUTINE:    CBloodClientShell::OnEngineInitialized()
  852. //
  853. //    PURPOSE:    Called upon engine initialization.
  854. //
  855. // --------------------------------------------------------------------------- //
  856. DRESULT CBloodClientShell::OnEngineInitialized(RMode *pMode, DGUID *pAppGuid)
  857. {
  858.     // Local variables...
  859.  
  860.     HCONSOLEVAR hVar;
  861.     CClientDE* pClientDE = GetClientDE();
  862.     DBOOL bPlayingMovies = DFALSE;
  863.     DRESULT resInitSound;
  864.     HSTRING hstrError;
  865.     char *pszError;
  866.  
  867.     // Set the guid...
  868.  
  869.     *pAppGuid = BLOOD2GUID;
  870.  
  871.     // Init Move mgr...
  872.     m_pMoveMgr = new CMoveMgr(this);
  873.     if(!m_pMoveMgr)
  874.         return LT_ERROR;
  875.  
  876.     m_pMoveMgr->Init(pClientDE);
  877.  
  878.     // Initialize The Voice data...
  879.     TheVoice_Init(pClientDE);
  880.  
  881.     // Initialize the physics states...
  882.     g_normalPhysicsState.m_pClientDE = pClientDE;
  883.     VEC_SET(g_normalPhysicsState.m_GravityAccel, 0.0f, -1000.0f, 0.0f);
  884.     g_normalPhysicsState.m_VelocityDampen = 0.35f;
  885.  
  886.     g_waterPhysicsState.m_pClientDE = pClientDE;
  887.     VEC_SET(g_waterPhysicsState.m_GravityAccel, 0.0f, -500.0f, 0.0f);
  888.     g_waterPhysicsState.m_VelocityDampen = 0.20f;
  889.  
  890.     // Initialize sound...
  891.     resInitSound = InitSound();
  892.  
  893.     // Add to NumRuns count...
  894.     float nNumRuns = 0.0f;
  895.     hVar = pClientDE->GetConsoleVar ("NumRuns");
  896.     if (hVar)
  897.     {
  898.         nNumRuns = pClientDE->GetVarValueFloat (hVar);
  899.     }
  900.     nNumRuns++;
  901.     
  902.     char strConsole[64];
  903.     sprintf (strConsole, "+NumRuns %f", nNumRuns);
  904.     pClientDE->RunConsoleString (strConsole);
  905.  
  906.  
  907.     // Format some strings...
  908.  
  909.     m_hCtfCapturedString1 = pClientDE->FormatString(IDS_CTF_CAPTURED_1);
  910.     m_hCtfCapturedString2 = pClientDE->FormatString(IDS_CTF_CAPTURED_2);
  911.  
  912. #ifdef _ADDON
  913.     m_hSoccerGoalString1 = pClientDE->FormatString(IDS_SOCCER_GOAL_1);
  914.     m_hSoccerGoalString2 = pClientDE->FormatString(IDS_SOCCER_GOAL_2);
  915. #endif // _ADDON
  916.  
  917.  
  918.     // check advanced options...
  919.  
  920.     hVar = pClientDE->GetConsoleVar ("DisableMusic");
  921.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableMusic = DTRUE;
  922.     hVar = pClientDE->GetConsoleVar ("DisableSound");
  923.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableSound = DTRUE;
  924.     hVar = pClientDE->GetConsoleVar ("DisableMovies");
  925.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableMovies = DTRUE;
  926.     hVar = pClientDE->GetConsoleVar ("DisableJoystick");
  927.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableJoystick = DTRUE;
  928.     hVar = pClientDE->GetConsoleVar ("EnableOptSurf");
  929.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedEnableOptSurf = DTRUE;
  930.     hVar = pClientDE->GetConsoleVar ("DisableLightMap");
  931.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableLightMap = DTRUE;
  932.     hVar = pClientDE->GetConsoleVar ("EnableTripBuf");
  933.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedEnableTripBuf = DTRUE;
  934.     hVar = pClientDE->GetConsoleVar ("DisableDx6Cmds");
  935.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableDx6Cmds = DTRUE;
  936.     hVar = pClientDE->GetConsoleVar ("EnableTJuncs");
  937.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedEnableTJuncs = DTRUE;
  938.     hVar = pClientDE->GetConsoleVar ("DisableFog");
  939.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableFog = DTRUE;
  940.     hVar = pClientDE->GetConsoleVar ("DisableLines");
  941.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableLines = DTRUE;
  942.     hVar = pClientDE->GetConsoleVar ("DisableModelFB");
  943.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedDisableModelFB = DTRUE;
  944.     hVar = pClientDE->GetConsoleVar ("EnablePixDub");
  945.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedEnablePixelDoubling = DTRUE;
  946.     hVar = pClientDE->GetConsoleVar ("EnableMultiTex");
  947.     if (hVar && pClientDE->GetVarValueFloat (hVar))        m_bAdvancedEnableMultiTexturing = DTRUE;
  948.  
  949.     // Set the detail console variables
  950.     MenuSetDetail();
  951.  
  952.     // Set the player cursor display
  953.     hVar = pClientDE->GetConsoleVar ("Crosshair");
  954.     if(hVar && pClientDE->GetVarValueFloat(hVar))
  955.     {
  956.         m_bShowCrosshair = DTRUE;
  957.         m_bCrosshairOriginallyOn = DTRUE;
  958.     }
  959.     else
  960.     {
  961.         m_bShowCrosshair = DFALSE;
  962.         m_bCrosshairOriginallyOn = DFALSE;
  963.     }
  964.  
  965.     hVar = pClientDE->GetConsoleVar ("CrosshairNum");
  966.     m_nCrosshair = (DBYTE)pClientDE->GetVarValueFloat(hVar);
  967.     if(m_nCrosshair > 41) m_nCrosshair = 0;
  968.     m_nCrosshairOriginalNum = m_nCrosshair;
  969.  
  970.     // Set the player movement variables (mouselook)
  971.     hVar = pClientDE->GetConsoleVar ("MouseLook");
  972.     if(hVar && pClientDE->GetVarValueFloat(hVar))
  973.     {
  974.         m_bMouseLook = DTRUE;
  975. //        cdata.byFlags |= CDATA_MOUSEAIMING;
  976.     }
  977.     else
  978.     {
  979.         m_bMouseLook = DFALSE;
  980. //        cdata.byFlags &= ~CDATA_MOUSEAIMING;
  981.     }
  982.  
  983.     // Set the player movement variables (lookspring)
  984.     hVar = pClientDE->GetConsoleVar ("LookSpring");
  985.     if(hVar && pClientDE->GetVarValueFloat(hVar))
  986.     {
  987.         m_bLookSpring = DTRUE;
  988.     }
  989.     else
  990.     {
  991.         m_bLookSpring = DFALSE;
  992.     }
  993.  
  994.     // Set the player movement variables (runlock)
  995.     hVar = pClientDE->GetConsoleVar ("RunLock");
  996.     if(hVar && pClientDE->GetVarValueFloat(hVar))
  997.         cdata.byFlags |= CDATA_RUNLOCK;
  998.     else
  999.         cdata.byFlags &= ~CDATA_RUNLOCK;
  1000.  
  1001.     // Turn on client side prediction
  1002.     pClientDE->RunConsoleString("Prediction 1");
  1003.  
  1004.  
  1005.     // Determine if we were lobby launched...
  1006.  
  1007.     DBOOL bNetworkGameStarted = DFALSE;
  1008.     DBOOL bLobbyLaunched      = DFALSE;
  1009.  
  1010. #ifndef _DEMO
  1011.     DRESULT dr = pClientDE->IsLobbyLaunched("dplay2");
  1012.     if (dr == LT_OK)
  1013.     {
  1014.         DBOOL bRet = NetStart_DoLobbyLaunchWizard(pClientDE);
  1015.         if (bRet)
  1016.         {
  1017.             bLobbyLaunched      = DTRUE;
  1018.             bNetworkGameStarted = DTRUE;
  1019.         }
  1020.         else
  1021.         {
  1022.             pClientDE->Shutdown();
  1023.             return LT_ERROR;
  1024.         }
  1025.     }
  1026. #endif
  1027.  
  1028.  
  1029.     // Check for console vars that say we should do networking setup stuff...
  1030.     DBOOL bDoNetStuff = DFALSE;
  1031.  
  1032.     hVar = pClientDE->GetConsoleVar("Multiplayer");
  1033.     if (hVar)
  1034.     {
  1035.         if ((DBOOL)pClientDE->GetVarValueFloat(hVar)) bDoNetStuff = DTRUE;
  1036.     }
  1037.  
  1038.     hVar = pClientDE->GetConsoleVar("ConnectPlr");
  1039.     if (hVar)
  1040.     {
  1041.         char* sVar = pClientDE->GetVarValueString(hVar);
  1042.         if (sVar && sVar[0] != '\0' && _mbscmp((const unsigned char*)sVar, (const unsigned char*)"0") != 0) bDoNetStuff = DTRUE;
  1043.     }
  1044.  
  1045.     hVar = pClientDE->GetConsoleVar("Connect");
  1046.     if (hVar)
  1047.     {
  1048.         char* sVar = pClientDE->GetVarValueString(hVar);
  1049.         if (sVar && sVar[0] != '\0' && _mbscmp((const unsigned char*)sVar, (const unsigned char*)"0") != 0) bDoNetStuff = DTRUE;
  1050.     }
  1051.  
  1052.     if (bLobbyLaunched) bDoNetStuff = DFALSE;
  1053.  
  1054. #ifdef _DEMO
  1055.     bDoNetStuff = DFALSE;
  1056. #endif
  1057.  
  1058.     // Determine if we should display the networking dialogs...
  1059.     if (bDoNetStuff)
  1060.     {
  1061.         bNetworkGameStarted = NetStart_DoWizard (pClientDE);
  1062.  
  1063.         if (!bNetworkGameStarted)
  1064.         {
  1065.             pClientDE->Shutdown();
  1066.             return LT_ERROR;
  1067.         }
  1068.     }
  1069.  
  1070.     // Pass RMode on to SetRenderMode...
  1071.     DRESULT hResult = pClientDE->SetRenderMode(pMode);
  1072.     if (hResult != LT_OK)
  1073.     {
  1074.         // If an error occurred, try 640x480x16...
  1075.         
  1076.         RMode rMode;
  1077.  
  1078.         rMode.m_Width        = 640;
  1079.         rMode.m_Height        = 480;
  1080.         rMode.m_BitDepth    = 16;
  1081.         rMode.m_bHardware    = pMode->m_bHardware;
  1082.  
  1083.         sprintf(rMode.m_RenderDLL, "%s", pMode->m_RenderDLL);
  1084.         sprintf(rMode.m_InternalName, "%s", pMode->m_InternalName);
  1085.         sprintf(rMode.m_Description, "%s", pMode->m_Description);
  1086.  
  1087.         if (pClientDE->SetRenderMode(&rMode) != LT_OK)
  1088.         {
  1089.             // Okay, that didn't work, looks like we're stuck with software...
  1090.         
  1091.             rMode.m_bHardware = DFALSE;
  1092.  
  1093.             sprintf(rMode.m_RenderDLL, "soft.ren");
  1094.             sprintf(rMode.m_InternalName, "");
  1095.             sprintf(rMode.m_Description, "");
  1096.  
  1097.             if (pClientDE->SetRenderMode(&rMode) != LT_OK)
  1098.             {
  1099.                 Abort(IDS_ERR_SETVIDMODE, 6929314);
  1100.                 return LT_ERROR;
  1101.             } 
  1102.         }
  1103.     }
  1104.  
  1105.     // Draw the loading screen if we are hosting a network game already...
  1106.     if (bNetworkGameStarted && g_bIsHost)
  1107.     {
  1108.         DrawLoadingScreen();
  1109.         pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE);
  1110.         DrawLoadingScreen();
  1111.     }
  1112.  
  1113.     // Register console commands
  1114.     pClientDE->RegisterConsoleProgram("LeakFile", LeakFileFn);
  1115.     pClientDE->RegisterConsoleProgram("Connect", ConnectFn);
  1116.     pClientDE->RegisterConsoleProgram("FragSelf", FragSelfFn);
  1117.     pClientDE->RegisterConsoleProgram("InitSound", InitSoundFn);
  1118.     pClientDE->RegisterConsoleProgram("NextLevel", NextLevelFn);
  1119.     pClientDE->RegisterConsoleProgram("Load", LoadLevelFn);
  1120.  
  1121.     // Try to initialize the level manager (including
  1122. //    if (!m_LevelMgr.Init(pClientDE))
  1123. //    {
  1124. //        PrintError("Could not init LevelMgr");
  1125. //        return LT_ERROR;
  1126. //    }
  1127.  
  1128.     // Setup the music stuff...
  1129.     if( !m_Music.IsInitialized( ))
  1130.     {
  1131.         HCONSOLEVAR hConsoleVar;
  1132.         hConsoleVar = pClientDE->GetConsoleVar( "musictype" );
  1133.  
  1134.         // Default to ima if music never set before...
  1135.         if( !hConsoleVar )
  1136.             m_Music.Init( pClientDE, DTRUE );
  1137.         else
  1138.         {
  1139.             // See if they want cdaudio or ima...
  1140.             if(_mbsicmp((const unsigned char*)pClientDE->GetVarValueString( hConsoleVar ), (const unsigned char*)"cdaudio" ) == 0 )
  1141.                 m_Music.Init( pClientDE, DFALSE );
  1142.             else
  1143.                 m_Music.Init( pClientDE, DTRUE );
  1144.         }
  1145.     }
  1146.  
  1147.     // Set the sound volume
  1148.     hVar = pClientDE->GetConsoleVar("SoundVolume");
  1149.     if (hVar)
  1150.     {
  1151.         pClientDE->SetSoundVolume((int)pClientDE->GetVarValueFloat(hVar));
  1152.     }
  1153.     else
  1154.     {
  1155.         pClientDE->SetSoundVolume(35);
  1156.     }
  1157.     
  1158.     // Set the music volume
  1159.     hVar = pClientDE->GetConsoleVar("MusicVolume");
  1160.     if (hVar)
  1161.     {
  1162.         pClientDE->SetMusicVolume((int)pClientDE->GetVarValueFloat(hVar));
  1163.     }
  1164.     else
  1165.     {
  1166.         pClientDE->SetMusicVolume(35);
  1167.     }
  1168.  
  1169.     // Set the mouse sensitivity
  1170.     m_fOriginalMouseSensitivity = GetMouseSensitivity();
  1171. //    SetMouseSensitivity(m_fOriginalMouseSensitivity);
  1172.     m_fOriginalKeyTurnRate = GetKeyboardTurnRate();
  1173. //    SetKeyboardTurnRate(m_fOriginalKeyTurnRate);
  1174.  
  1175.     // Set the invert y-axis variable
  1176.     hVar=pClientDE->GetConsoleVar("MouseInvertYAxis");
  1177.     if (hVar && (int)pClientDE->GetVarValueFloat(hVar) != 0)
  1178.     {
  1179.         m_bMouseInvertYAxis=DTRUE;
  1180.     }
  1181.     else
  1182.     {
  1183.         m_bMouseInvertYAxis=DFALSE;
  1184.     }
  1185.  
  1186.     // Set the use joystick variable
  1187.     hVar=pClientDE->GetConsoleVar("UseJoystick");
  1188.     if (hVar && (int)pClientDE->GetVarValueFloat(hVar) != 0)
  1189.     {
  1190.         m_bUseJoystick=DTRUE;
  1191.     }
  1192.     else
  1193.     {
  1194.         m_bUseJoystick=DFALSE;
  1195.     }
  1196.  
  1197.     // Set the keyboard turn rate    
  1198.     hVar=pClientDE->GetConsoleVar("KeyboardTurnRate");
  1199.     if (hVar)
  1200.     {
  1201.         m_fKeyboardTurnRate=pClientDE->GetVarValueFloat(hVar);
  1202.     }    
  1203.     else
  1204.     {
  1205.         m_fKeyboardTurnRate=1.0f;
  1206.     }
  1207.  
  1208. /*
  1209.     if (m_Music.IsInitialized())
  1210.     {
  1211.         // Only re-init if not already using ima...
  1212.         if (!m_Music.UsingIMA())
  1213.         {
  1214.             // preserve the music level, just in case we come back to ima...
  1215.             CMusic::EMusicLevel level;
  1216.             level = m_Music.GetMusicLevel();
  1217.             if (m_Music.Init (pClientDE, DTRUE))
  1218.             {
  1219.                 // Only start the music if we are in a world...
  1220.                 if (IsInWorld() && !pClientShell->IsFirstUpdate())
  1221.                 {
  1222.                     m_Music.InitPlayLists();
  1223.                     m_Music.PlayMusicLevel (level);
  1224.                 }
  1225.             }
  1226.         }
  1227.     }
  1228. */
  1229.     // Set the model hook function to do special model rendering...
  1230.     pClientDE->SetModelHook((ModelHookFn)DefaultModelHook, this);
  1231.  
  1232.     // Initialize the Message Mgr (T option)
  1233.     m_MessageMgr.Init(pClientDE);
  1234.     m_MessageMgr.Enable(DTRUE);
  1235.     
  1236.     // Initialize the Cheat Manager
  1237.     m_CheatMgr.Init(pClientDE);
  1238.  
  1239. #ifndef _DEMO
  1240.     m_FragInfo.Init(pClientDE, GetTeamMgr());
  1241. #endif
  1242.  
  1243.     HSTRING        szErrorStr = 0;
  1244.  
  1245.     // Initialize the Status bar
  1246.     if (!m_NewStatusBar.Init(pClientDE))
  1247.     {
  1248.         szErrorStr = pClientDE->FormatString(IDS_INITERR_STATUS);
  1249.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1250.         pClientDE->FreeString(szErrorStr);
  1251.         Abort(IDS_ERR_INITSTATUSBAR, 6929318);
  1252.         return LT_ERROR;
  1253.     }
  1254.  
  1255.     // Initialize the Status bar
  1256.     if (!m_CommLink.Init(pClientDE))
  1257.     {
  1258.         szErrorStr = pClientDE->FormatString(IDS_INITERR_COMMLINK);
  1259.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1260.         pClientDE->FreeString(szErrorStr);
  1261.         Abort(IDS_ERR_INITSTATUSBAR, 6929317);
  1262.         return LT_ERROR;
  1263.     }
  1264.  
  1265.     // Initialize the Menu
  1266.     if (!m_Menu.Init (pClientDE))
  1267.     {
  1268.         szErrorStr = pClientDE->FormatString(IDS_INITERR_MENUS);
  1269.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1270.         pClientDE->FreeString(szErrorStr);
  1271.         Abort(IDS_ERR_INITMENU, 6929316);
  1272.         return LT_ERROR;
  1273.     }
  1274.  
  1275.     // Init the special fx mgr...
  1276.     if (!m_sfxMgr.Init(pClientDE))
  1277.       {
  1278.         szErrorStr = pClientDE->FormatString(IDS_INITERR_SFX);
  1279.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1280.         pClientDE->FreeString(szErrorStr);
  1281.         Abort(IDS_ERR_INITSFXMGR, 6929315);
  1282.         return LT_ERROR;
  1283.     }
  1284.  
  1285.     // Init the voice manager...
  1286.     if (!m_VoiceMgr.Init(pClientDE))
  1287.     {
  1288.         szErrorStr = pClientDE->FormatString(IDS_INITERR_VOICE);
  1289.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1290.         pClientDE->FreeString(szErrorStr);
  1291.         Abort(IDS_ERR_INITVOICEMGR, 61011701);
  1292.         return LT_ERROR;
  1293.     }
  1294.  
  1295.     if (!m_playerCamera.Init(pClientDE))
  1296.     {
  1297.         szErrorStr = pClientDE->FormatString(IDS_INITERR_CAMERA);
  1298.         CSPrint(pClientDE->GetStringData(szErrorStr));
  1299.         pClientDE->FreeString(szErrorStr);
  1300.         Abort(IDS_ERR_INITPLAYERCAMERA, 6929318);
  1301.         return LT_ERROR;
  1302.     }
  1303.     else
  1304.     {
  1305.         DVector vOffset;
  1306.         VEC_SET(vOffset, 0.0f, 30.0f, 0.0f);
  1307.  
  1308. //        m_playerCamera.SetDistUp(1000.0f);
  1309. //        m_playerCamera.SetPointAtOffset(vOffset);
  1310. //        m_playerCamera.SetChaseOffset(vOffset);
  1311.         m_playerCamera.SetDeathOffset(vOffset);
  1312.         m_playerCamera.SetFirstPerson();
  1313.         m_b3rdPerson = DFALSE;
  1314.     }
  1315.  
  1316.     if (!bNetworkGameStarted)
  1317.     {
  1318.         StartGameRequest request;
  1319.         memset( &request, 0, sizeof( StartGameRequest ));
  1320.  
  1321.         NetStart_ClearGameStruct();  // Start with clean slate
  1322.         request.m_pGameInfo   = NetStart_GetGameStruct();
  1323.         request.m_GameInfoLen = sizeof(NetGame_t);
  1324.  
  1325.         HCONSOLEVAR hVar;
  1326.  
  1327.         // Set the Console lines
  1328.         if (hVar = pClientDE->GetConsoleVar("NumConsoleLines"))
  1329.         {
  1330.             DFLOAT fLines = pClientDE->GetVarValueFloat(hVar);
  1331.     //        m_MessageMgr.SetMaxMessages((int)fLines);
  1332.             m_MessageMgr.SetMaxMessages((int)6);
  1333.             pClientDE->RunConsoleString("NumConsoleLines 0");
  1334.         }
  1335.         
  1336.         // Get the command line world, if found
  1337.         if (hVar = pClientDE->GetConsoleVar("runworld"))
  1338.         {
  1339.             char *pWorldName = pClientDE->GetVarValueString(hVar);
  1340.  
  1341.             StartNewGame(pWorldName, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM);
  1342.             m_bFirstWorld = DTRUE;
  1343.         }
  1344.         else
  1345.         {
  1346.             if (!StartMovies(pClientDE))
  1347.             {
  1348.                 bPlayingMovies = DFALSE;
  1349.                 SetGameState(GS_MENU);
  1350.                 m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  1351.             }
  1352.             else
  1353.             {
  1354.                 bPlayingMovies = DTRUE;
  1355.             }
  1356.         }
  1357.     }
  1358.     else
  1359.     {
  1360.         // Set the game state for a net game that is loading...
  1361.         SetGameState(GS_MPLOADINGLEVEL);
  1362.     }
  1363.  
  1364.     // Display the title screen if we're not playing movies...
  1365.  
  1366.     HSURFACE hTitleSurface = DNULL;
  1367.     DFLOAT     fTitleTime    = CWinUtil::GetTime();
  1368.  
  1369.     if (!bPlayingMovies && !bNetworkGameStarted)
  1370.     {
  1371. #ifndef _DEBUG
  1372.  
  1373. #ifdef _ADDON
  1374.         hTitleSurface = Splash_Display(pClientDE, "\\screens_ao\\title.pcx", DTRUE);
  1375. #else
  1376.         hTitleSurface = Splash_Display(pClientDE, "\\screens\\title.pcx", DTRUE);
  1377. #endif
  1378.  
  1379.         fTitleTime    = CWinUtil::GetTime();
  1380. #endif
  1381.     }
  1382.  
  1383.     // Read the player.cfg file, or defaultplayer.cfg if you can't find it.
  1384. //    if (!LoadConfig("player.cfg", &m_Config))
  1385. //        LoadConfig("defaultplayer.cfg", &m_Config);
  1386.  
  1387. #ifdef BRANDED
  1388.     // Initialize brand stuff
  1389.     CreateBrandSurface();
  1390. #endif
  1391.  
  1392.     // Seed the random number generator
  1393.     if ( pClientDE )
  1394.     {
  1395.         int nSeed=(int)(CWinUtil::GetTime() * 1000.0f);
  1396.         srand(nSeed);
  1397.     }
  1398.  
  1399.     // Initialize the message box font
  1400.     m_messageFont.Init(pClientDE, "interface/fonts/MenuFont1.pcx", "interface/fonts/MenuFont1.fnt");
  1401.     
  1402.     // Initialize the message box
  1403.     m_messageBox.Create(pClientDE, "interface/mainmenus/dialog.pcx", &m_messageFont, DNULL, DNULL);
  1404.     m_messageBox.SetTextColor(SETRGB(255, 255, 255));
  1405.  
  1406.     // Make sure the title screen has been up long enough...
  1407.     if (hTitleSurface)
  1408.     {
  1409.  
  1410. #ifndef _DEBUG
  1411.         CWinUtil::TimedKeyWait(VK_ESCAPE, VK_RETURN, VK_SPACE, 6.0f);
  1412. #endif
  1413.         pClientDE->DeleteSurface(hTitleSurface);
  1414.         hTitleSurface = DNULL;
  1415.  
  1416.         CWinUtil::Sleep(50);
  1417.     }
  1418.  
  1419.     // Remove any stray keypresses...
  1420.     CWinUtil::RemoveKeyDownMessages();
  1421.  
  1422.     // Show error if sound didn't initialize properly
  1423.     if( resInitSound != LT_OK )
  1424.     {
  1425.         if( resInitSound == LT_NO3DSOUNDPROVIDER )
  1426.         {
  1427.             hstrError = pClientDE->FormatString( IDS_MESSAGE_INVALID3DSOUNDPROVIDER );
  1428.         }
  1429.         else
  1430.         {
  1431.             hstrError = pClientDE->FormatString( IDS_MESSAGE_SOUNDERROR );
  1432.         }
  1433.  
  1434.         pszError = pClientDE->GetStringData( hstrError );
  1435.         DoMessageBox( pszError );
  1436.         pClientDE->FreeString( hstrError );
  1437.     }
  1438.  
  1439.     // All done...
  1440.     return LT_OK;
  1441. }
  1442.  
  1443.     
  1444. // --------------------------------------------------------------------------- //
  1445. //
  1446. //    ROUTINE:    CBloodClientShell::OnEngineTerm()
  1447. //
  1448. //    PURPOSE:    Called upon engine termination.
  1449. //
  1450. // --------------------------------------------------------------------------- //
  1451.  
  1452. void CBloodClientShell::OnEngineTerm()
  1453. {
  1454.     CClientDE* pClientDE = GetClientDE();
  1455.  
  1456.     m_Menu.Term();
  1457.     m_MessageMgr.Term();
  1458.     m_VoiceMgr.Term();
  1459.     m_NewStatusBar.Term();
  1460.     m_CommLink.Term();
  1461.     m_Music.Term( );
  1462.     if (m_Credits.IsInited())
  1463.         m_Credits.Term();
  1464.  
  1465.     if (m_hCrosshair)
  1466.         pClientDE->DeleteSurface(m_hCrosshair);
  1467.  
  1468.     // Terminate the message box and its font
  1469.     m_messageFont.Term();
  1470.     m_messageBox.Destroy();
  1471.  
  1472.     // Deal with some advanced options...
  1473.  
  1474.     if (m_bSoundOriginallyEnabled && AdvancedDisableSound())
  1475.     {
  1476.         pClientDE->RunConsoleString ("SoundEnable 1");
  1477.     }
  1478.  
  1479.     if (m_bMusicOriginallyEnabled && AdvancedDisableMusic())
  1480.     {
  1481.         pClientDE->RunConsoleString ("MusicEnable 1");
  1482.     }
  1483.  
  1484.     if (m_bModelFBOriginallyEnabled)
  1485.     {
  1486.         pClientDE->RunConsoleString ("ModelFullbrite 1");
  1487.     }
  1488.  
  1489.     if (m_bLightmappingOriginallyEnabled)
  1490.     {
  1491.         pClientDE->RunConsoleString ("LightMap 1");
  1492.     }
  1493. }
  1494.  
  1495.  
  1496. // --------------------------------------------------------------------------- //
  1497. //
  1498. //    ROUTINE:    CBloodClientShell::OnEnterWorld()
  1499. //
  1500. //    PURPOSE:    Function called when the client first enters the world.
  1501. //
  1502. // --------------------------------------------------------------------------- //
  1503.  
  1504. void CBloodClientShell::OnEnterWorld()
  1505. {
  1506.     CClientDE* pClientDE = GetClientDE();
  1507.     if (!pClientDE) return;
  1508.  
  1509.     m_bInWorld = DTRUE;
  1510.     m_bHandledStartup = DFALSE;
  1511.  
  1512.     m_bFadeIn = m_bFadeOut = DFALSE;
  1513.  
  1514.     if (!m_hCamera)
  1515.     {
  1516.         ObjectCreateStruct cocStruct;
  1517.         INIT_OBJECTCREATESTRUCT(cocStruct);
  1518.     
  1519.         cocStruct.m_ObjectType = OT_CAMERA;
  1520.         VEC_INIT(cocStruct.m_Pos)
  1521.         ROT_INIT(cocStruct.m_Rotation)
  1522.         cocStruct.m_Flags = 0;
  1523.  
  1524.         m_hCamera = pClientDE->CreateObject(&cocStruct);
  1525.     }
  1526.     pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &m_dwScreenWidth, &m_dwScreenHeight);
  1527.     m_fovX = DEG2RAD(m_DefFovX);
  1528.     m_fovY = m_fovX * m_fovYScale;
  1529.     
  1530.     pClientDE->SetCameraFOV(m_hCamera, m_fovX, m_fovY);
  1531.  
  1532.     // Initialize various variables
  1533.     m_SpinAmount = 0;
  1534.     m_bZeroXAngle = DFALSE;
  1535.     m_fBobPhase = m_fSwayPhase = 0;
  1536.     m_fBobHeight = m_fBobWidth = m_fBobCant = m_fShakeCant = 0;
  1537.     m_fViewKick = m_fKickTime = 0;
  1538.  
  1539. //    m_fVelY = 0.0f;
  1540.     m_fViewY = m_fViewYVel = 0.0f;
  1541.     m_fWeaponY = m_fWeaponYVel = 0.0f;
  1542.  
  1543.     m_fVelMagnitude        = 0;
  1544.     m_fEyeLevel            = 0;
  1545.     VEC_INIT(m_vMyLastPos);
  1546.  
  1547.     m_bDead                = DFALSE;
  1548.     m_bDeadNoHide       = DFALSE;
  1549.     m_bWonkyVision        = DFALSE;
  1550.     m_bWonkyNoMove      = DFALSE;
  1551.     m_fWonkyTime        = 0.0f;
  1552.  
  1553.     m_bShakeScreen        = DFALSE;
  1554.     m_fShakeTime        = 0.0f;
  1555.     m_fShakeStart        = 0.0f;
  1556.     VEC_INIT(m_vShakeMagnitude);
  1557.  
  1558.     m_bFlashScreen        = DFALSE;
  1559.     m_fFlashTime        = 0.0f;
  1560.     m_fFlashStart        = 0.0f;
  1561.     m_fFlashRampUp        = 0.0f;
  1562.     VEC_INIT(m_vFlashColor);
  1563.  
  1564.     ROT_INIT(m_Rotation)
  1565.  
  1566.     // Sky panning
  1567.     m_bPanSky            = DFALSE;
  1568.     m_fPanSkyOffsetX    = 1.0f;
  1569.     m_fPanSkyOffsetZ    = 1.0f;
  1570.     m_fPanSkyScaleX        = 1.0f;
  1571.     m_fPanSkyScaleZ        = 1.0f;
  1572.     m_fCurSkyXOffset    = 0.0f;
  1573.     m_fCurSkyZOffset    = 0.0f;
  1574.  
  1575.     // Send initial update message
  1576. //    SendPlayerUpdateMessage(DTRUE);
  1577.  
  1578.     m_fCameraZoom = 0;
  1579.     m_b3rdPerson = DFALSE;
  1580.     m_playerCamera.SetFirstPerson();
  1581.  
  1582.     m_bFirstUpdate = DTRUE;
  1583.  
  1584.     g_pClientDE->SetInputState(DTRUE);
  1585.     m_bDrawFragBar = DFALSE;
  1586.     g_bLevelChange3rdPersonCam = DFALSE;
  1587.     g_bLevelChangeNoUpdate     = DFALSE;
  1588.  
  1589.     cdataLast.byFlags = 0;
  1590.     // Stuff to initialize/send if this is the first world
  1591.     if (m_bFirstWorld)
  1592.     {
  1593.         m_nCurGun = 0;
  1594.  
  1595.         m_bSpectatorMode = DFALSE;
  1596.     
  1597.         m_bZoomView = DFALSE;
  1598. //        m_bStoneView = DFALSE;
  1599. //        m_bAuraView = DFALSE;
  1600.  
  1601.         if( m_hNightGogglesSound )
  1602.         {
  1603.             g_pClientDE->KillSound( m_hNightGogglesSound );
  1604.             m_hNightGogglesSound = DNULL;
  1605.         }
  1606.  
  1607.         if( m_hTheEyeLoopingSound )
  1608.         {
  1609.             g_pClientDE->KillSound( m_hTheEyeLoopingSound );
  1610.             m_hTheEyeLoopingSound = DNULL;
  1611.         }
  1612.  
  1613.         int mode = 0;
  1614.         if (pClientDE->GetGameMode(&mode) == DE_OK)
  1615.         {
  1616.             if (mode == STARTGAME_NORMAL)    // Single player game name irrelevant
  1617.                 _mbscpy((unsigned char*)m_Config.szName, (const unsigned char*)"");
  1618.         }
  1619.  
  1620.         m_nLastExitType = -1;
  1621.  
  1622.         m_CheatMgr.Reset();
  1623.     }
  1624.  
  1625.     // Reset the status bar
  1626.     m_NewStatusBar.Reset();
  1627.  
  1628.     //SCHLEGZ 4/27/98 5:45:03 PM: automatically turn on vis lsit deactivation
  1629.     pClientDE->RunConsoleString("serv autodeactivate 1");
  1630.  
  1631.     m_Music.TermPlayLists();
  1632.     m_Music.InitPlayLists( );
  1633.     if ( !m_Music.UsingIMA( ))
  1634.         m_Music.PlayCDList( );
  1635.     else
  1636.         m_Music.PlayMusicLevel( m_eMusicLevel );
  1637.  
  1638.     VEC_INIT( m_vLastReverbPos );
  1639.  
  1640. }
  1641.  
  1642.  
  1643. // --------------------------------------------------------------------------- //
  1644. //
  1645. //    ROUTINE:    CBloodClientShell::OnExitWorld()
  1646. //
  1647. //    PURPOSE:    Called when the client leaves the world.  Perform cleanup here.
  1648. //
  1649. // --------------------------------------------------------------------------- //
  1650. void CBloodClientShell::OnExitWorld()
  1651. {
  1652.     CClientDE* pClientDE = GetClientDE();
  1653.  
  1654.     m_sfxMgr.RemoveAll();                    // Remove all the sfx
  1655.  
  1656.     // Kill the music...
  1657.     pClientDE->StopMusic (MUSIC_IMMEDIATE);
  1658.     m_Music.TermPlayLists();
  1659.     m_eMusicLevel  = CMusic::MUSICLEVEL_SILENCE;
  1660.  
  1661.     // Pause sounds (this will only pause currently playing sounds, then they'll get removed)
  1662.     pClientDE->PauseSounds();
  1663.  
  1664.     m_playerCamera.AttachToObject(DNULL);    // Detatch camera
  1665.  
  1666.  
  1667.     if (m_hCamera)
  1668.     {
  1669.         pClientDE->DeleteObject(m_hCamera);
  1670.         m_hCamera = DNULL;
  1671.     }
  1672.  
  1673.     for (int i=0;i<CLIENTWEAPONSLOTS;i++)
  1674.     {
  1675.         m_abyWeaponID[i] = WEAP_NONE;
  1676.         m_abyLWeaponID[i] = WEAP_NONE;
  1677.     }
  1678.     if (m_pWeapon) 
  1679.     {
  1680.         delete m_pWeapon;
  1681.         m_pWeapon = DNULL;
  1682.     }
  1683.     if (m_pLWeapon) 
  1684.     {
  1685.         delete m_pLWeapon;
  1686.         m_pLWeapon = DNULL;
  1687.     }
  1688.  
  1689.     m_hWeapHandObj = DNULL;
  1690.     m_hLWeapHandObj = DNULL;
  1691.  
  1692.     if (m_hContainerSound)
  1693.     {
  1694.         pClientDE->KillSound(m_hContainerSound);
  1695.         m_hContainerSound = DNULL;
  1696.     }
  1697.  
  1698.     m_FragInfo.RemoveAllClients();
  1699.  
  1700.     m_bInWorld     = DFALSE;
  1701.     m_bRollCredits = DFALSE;
  1702.  
  1703.     m_Credits.Term();
  1704.  
  1705.     m_bNightGogglesActive = DFALSE;
  1706.     if( m_hNightGogglesSound )
  1707.     {
  1708.         g_pClientDE->KillSound( m_hNightGogglesSound );
  1709.         m_hNightGogglesSound = DNULL;
  1710.     }
  1711.  
  1712.     m_bBinocularsActive = DFALSE;
  1713.     m_hSeeingEyeObj = m_hOrbObj = m_hLastOrbObj = DNULL;
  1714.  
  1715.     if( m_hTheEyeLoopingSound )
  1716.     {
  1717.         g_pClientDE->KillSound( m_hTheEyeLoopingSound );
  1718.         m_hTheEyeLoopingSound = DNULL;
  1719.     }
  1720.  
  1721.     if( m_hstrObjectivesText )
  1722.     {
  1723.         g_pClientDE->FreeString( m_hstrObjectivesText );
  1724.         m_hstrObjectivesText = DNULL;
  1725.     }
  1726.     if( m_hstrObjectivesTitle )
  1727.     {
  1728.         g_pClientDE->FreeString( m_hstrObjectivesTitle );
  1729.         m_hstrObjectivesTitle = DNULL;
  1730.     }
  1731. }
  1732.  
  1733.  
  1734.  
  1735. // --------------------------------------------------------------------------- //
  1736. //
  1737. //    ROUTINE:    CBloodClientShell::SendPlayerUpdateMessage()
  1738. //
  1739. //    PURPOSE:    Sends player info to the server
  1740. //
  1741. // --------------------------------------------------------------------------- //
  1742.  
  1743. void CBloodClientShell::SendPlayerUpdateMessage(DBOOL bSendAll)
  1744. {
  1745.     // Get our client pointer...
  1746.  
  1747.     CClientDE* pClientDE = GetClientDE();
  1748.     if (!pClientDE) return;
  1749.  
  1750.  
  1751.     // Determine if it's time to update if we're in multiplayer...
  1752.  
  1753.     if (!bSendAll && IsMultiplayerGame())
  1754.     {
  1755.         g_fPlayerUpdateTimer -= pClientDE->GetFrameTime();
  1756.         if (g_fPlayerUpdateTimer > 0.0f) return;
  1757.         g_fPlayerUpdateTimer = PLAYER_MULTI_UPDATE_TIMER;
  1758.     }
  1759.  
  1760.  
  1761.     // Determine the update flags we want...
  1762.  
  1763.     DBYTE byUpdateFlags = 0;
  1764.  
  1765.     // HACK - send container code to server that is just below our eye
  1766.     DVector vPos;
  1767.     pClientDE->GetObjectPos(m_hCamera, &vPos);
  1768.     vPos.y -= 15.0f;
  1769.  
  1770.     HLOCALOBJ objList[1];
  1771.     DDWORD dwNum = pClientDE->GetPointContainers(&vPos, objList, 1);
  1772.  
  1773.     if (dwNum > 0)
  1774.     {
  1775.         D_WORD wCode;
  1776.         pClientDE->GetContainerCode(objList[0], &wCode );
  1777.         cdata.eContainer = ( ContainerCode )wCode;
  1778.     }
  1779.     else
  1780.         cdata.eContainer = m_eCurContainerCode;
  1781.  
  1782.     // HACK - send container code to server that is at our feet
  1783.     HOBJECT hPlayerObj;
  1784.     DVector vDims;
  1785.     hPlayerObj = m_pMoveMgr->GetObject( );
  1786.     if( hPlayerObj && !m_bDead )
  1787.     {
  1788.         pClientDE->GetObjectPos( hPlayerObj, &vPos );
  1789.         pClientDE->Physics( )->GetObjectDims( hPlayerObj, &vDims );
  1790.         vPos.y -= vDims.y;
  1791.  
  1792.         HLOCALOBJ objList[1];
  1793.         DDWORD dwNum = pClientDE->GetPointContainers( &vPos, objList, 1 );
  1794.  
  1795.         if (dwNum > 0)
  1796.         {
  1797.             cdata.hContainerAtBottom = objList[0];
  1798.         }
  1799.         else
  1800.             cdata.hContainerAtBottom = DNULL;
  1801.     }
  1802.     else
  1803.         cdata.hContainerAtBottom = DNULL;
  1804.  
  1805.     // Set mouse aiming
  1806.     if (m_bMouseLook || pClientDE->IsCommandOn(COMMAND_MOUSEAIMTOGGLE))
  1807.         cdata.byFlags |= CDATA_MOUSEAIMING;
  1808.     else
  1809.         cdata.byFlags &= ~CDATA_MOUSEAIMING;
  1810.  
  1811.  
  1812.     // Determine what we want to send..
  1813.     if (!bSendAll)
  1814.     {
  1815.         if (cdata.byFlags != cdataLast.byFlags)
  1816.             byUpdateFlags |= PLAYERUPDATE_FLAGS;
  1817.         
  1818.         if (cdata.fPitch != cdataLast.fPitch)
  1819.             byUpdateFlags |= PLAYERUPDATE_PITCH;
  1820.         
  1821.         if (cdata.fYaw != cdataLast.fYaw)
  1822.             byUpdateFlags |= PLAYERUPDATE_YAW;
  1823.         
  1824.         if (!VEC_EQU(cdata.GunMuzzlePos, cdataLast.GunMuzzlePos))
  1825.             byUpdateFlags |= PLAYERUPDATE_MUZZLE;
  1826.         
  1827.         if (!VEC_EQU(cdata.lGunMuzzlePos, cdataLast.lGunMuzzlePos))
  1828.             byUpdateFlags |= PLAYERUPDATE_LMUZZLE;
  1829.         
  1830.         if (cdata.MouseAxis0 != cdataLast.MouseAxis0 || cdata.MouseAxis1 != cdataLast.MouseAxis1)
  1831.         {
  1832.             byUpdateFlags |= PLAYERUPDATE_MOUSE;
  1833.         }
  1834.         if (cdata.eContainer != cdataLast.eContainer)
  1835.             byUpdateFlags |= PLAYERUPDATE_CONTAINER;
  1836.         if (cdata.hContainerAtBottom != cdataLast.hContainerAtBottom)
  1837.             byUpdateFlags |= PLAYERUPDATE_CONTAINERATBOTTOM;
  1838.     }
  1839.     else    // Send all params.
  1840.     {
  1841.         byUpdateFlags = 0xff;
  1842.     }
  1843.  
  1844.     // Send the stuff.
  1845.     if (byUpdateFlags)
  1846.     {
  1847.         HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_PLAYERUPDATE);
  1848.  
  1849.         pClientDE->WriteToMessageByte(hMsg, byUpdateFlags);                // Tell what we are updating
  1850.  
  1851.         if (byUpdateFlags & PLAYERUPDATE_FLAGS)
  1852.             pClientDE->WriteToMessageByte(hMsg, cdata.byFlags);            // Flags
  1853.         
  1854.         if (byUpdateFlags & PLAYERUPDATE_PITCH)
  1855.             pClientDE->WriteToMessageFloat(hMsg, cdata.fPitch);            // Rotation
  1856.         
  1857.         if (byUpdateFlags & PLAYERUPDATE_YAW)
  1858.             pClientDE->WriteToMessageFloat(hMsg, cdata.fYaw);
  1859.         
  1860.         if (byUpdateFlags & PLAYERUPDATE_MUZZLE)
  1861.             pClientDE->WriteToMessageCompVector(hMsg, &cdata.GunMuzzlePos); // Muzzle pos
  1862.         
  1863.         if (byUpdateFlags & PLAYERUPDATE_LMUZZLE)
  1864.             pClientDE->WriteToMessageCompVector(hMsg, &cdata.lGunMuzzlePos); // Muzzle pos
  1865.         
  1866.         if (byUpdateFlags & PLAYERUPDATE_MOUSE)
  1867.         {
  1868.             DFLOAT fMouse0 = cdata.MouseAxis0 * 512;
  1869.             CLIPLOWHIGH(fMouse0, -128, 127);
  1870.             fMouse0 += 128;
  1871.             DFLOAT fMouse1 = cdata.MouseAxis1 * 512;
  1872.             CLIPLOWHIGH(fMouse1, -128, 127);
  1873.             fMouse1 += 128;
  1874.  
  1875.             pClientDE->WriteToMessageByte(hMsg, (DBYTE)fMouse0);            // Mouse axis
  1876.             pClientDE->WriteToMessageByte(hMsg, (DBYTE)fMouse1);
  1877.         }
  1878.  
  1879.         if (byUpdateFlags & PLAYERUPDATE_CONTAINER)
  1880.         {
  1881.             DBYTE nContainerCode;
  1882.  
  1883.             nContainerCode = (DBYTE) cdata.eContainer;
  1884.             if( m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj )
  1885.                 nContainerCode |= 0x80;
  1886.             pClientDE->WriteToMessageByte(hMsg, nContainerCode );    // Container code
  1887.         }
  1888.  
  1889.         if (byUpdateFlags & PLAYERUPDATE_CONTAINERATBOTTOM )
  1890.         {
  1891.             pClientDE->WriteToMessageObject(hMsg, cdata.hContainerAtBottom );
  1892.         }
  1893.  
  1894.         pClientDE->EndMessage(hMsg);
  1895.     }
  1896.     // Save current cdata
  1897.     memcpy(&cdataLast, &cdata, sizeof(ClientData));
  1898.  
  1899.     // Send position packet
  1900.     HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_PLAYERPOSITION);
  1901.  
  1902.     // Write position info.
  1903.     m_pMoveMgr->WritePositionInfo(hMessage);
  1904.  
  1905.     pClientDE->EndMessage2(hMessage, 0); // Send unguaranteed.
  1906.     
  1907. //    m_fLastSentYaw    = m_fYaw;
  1908. //    m_fLastSentCamCant = m_fCamCant;
  1909. //    m_fPlayerInfoLastSendTime = pClientDE->GetTime();
  1910. //    m_nPlayerInfoChangeFlags = 0;
  1911.  
  1912. }
  1913.  
  1914.  
  1915. // --------------------------------------------------------------------------- //
  1916. //
  1917. //    ROUTINE:    CBloodClientShell::SendPlayerInitMessage()
  1918. //
  1919. //    PURPOSE:    Sends a message to the server.
  1920. //
  1921. // --------------------------------------------------------------------------- //
  1922. void CBloodClientShell::SendPlayerInitMessage(DBYTE messageID)
  1923. {
  1924.     HMESSAGEWRITE hMsg;
  1925.     CClientDE* pClientDE = GetClientDE();
  1926.  
  1927.     if (messageID != CMSG_SINGLEPLAYER_INIT && messageID != CMSG_MULTIPLAYER_INIT)
  1928.         return;
  1929.  
  1930.     // Only send this if it's a new game.
  1931.     if (messageID == CMSG_SINGLEPLAYER_INIT && m_nLastLoadType != LOADTYPE_NEW_GAME)
  1932.         return;
  1933.  
  1934.     // Start the message
  1935.     hMsg = pClientDE->StartMessage(messageID);
  1936.  
  1937.     // Send the appropriate data for this message
  1938.     switch(messageID)
  1939.     {
  1940.         case CMSG_SINGLEPLAYER_INIT:
  1941.         case CMSG_MULTIPLAYER_INIT:
  1942.             {
  1943.                 int i;
  1944.                 HSTRING hstrName = DNULL;
  1945.  
  1946.                 // Load in a B2C file if it's a multiplayer game
  1947.                 if (IsMultiplayerGame())
  1948.                 {
  1949.                     NetPlayer* pPlayerInfo = NetStart_GetPlayerStruct();
  1950.                     if (!pPlayerInfo) return;
  1951.  
  1952.                     hstrName = pClientDE->CreateString(pPlayerInfo->m_sName);
  1953.  
  1954.                     B2C        b2cFile;
  1955.                     FILE    *file = 0;
  1956.                     char    filename[128];
  1957.  
  1958.                     if (strlen(pPlayerInfo->m_sConfig) <= 0)
  1959.                     {
  1960.                         CShell_GetConsoleString("NetConfigFile", pPlayerInfo->m_sConfig, "caleb.b2c");
  1961.                     }
  1962.  
  1963.                     sprintf(filename, "players\\%s", pPlayerInfo->m_sConfig);
  1964.  
  1965.                     if(file = fopen(filename, "rb"))
  1966.                     {
  1967.                         fread(&b2cFile, sizeof(B2C), 1, file);
  1968.                         fclose(file);
  1969.                     }
  1970.                     else    // just set default stuff
  1971.                     {
  1972.                         CSPrint("Warning - Unable to load .b2c file");
  1973.  
  1974.                         b2cFile.dwCharacter    = CHARACTER_CALEB;
  1975.                         b2cFile.dwColor        = 1;
  1976.                         b2cFile.dwStrength    = 5;
  1977.                         b2cFile.dwSpeed        = 3;
  1978.                         b2cFile.dwResist    = 3;
  1979.                         b2cFile.dwFocus        = 1;
  1980.                         b2cFile.dwWeap1        = 1;
  1981.                         b2cFile.dwWeap2        = 2;
  1982.                         b2cFile.dwWeap3        = 3;
  1983.                         b2cFile.dwWeap4        = 4;
  1984.                         b2cFile.dwWeap5        = 5;
  1985.                         b2cFile.dwWeap6        = 6;
  1986.                         b2cFile.dwWeap7        = 7;
  1987.                         b2cFile.dwWeap8        = 8;
  1988.                         b2cFile.dwWeap9        = 9;
  1989.                     }
  1990.  
  1991.                     m_Config.nCharacter = (DBYTE)b2cFile.dwCharacter;
  1992.                     m_Config.nSkin = (DBYTE)b2cFile.dwColor;
  1993.                     m_Config.nStrength = (DBYTE)b2cFile.dwStrength;
  1994.                     m_Config.nSpeed = (DBYTE)b2cFile.dwSpeed;
  1995.                     m_Config.nResistance = (DBYTE)b2cFile.dwResist;
  1996.                     m_Config.nMagic = (DBYTE)b2cFile.dwFocus;
  1997.                     m_Config.nWeaponSlots[1] = (DBYTE)b2cFile.dwWeap1;
  1998.                     m_Config.nWeaponSlots[2] = (DBYTE)b2cFile.dwWeap2;
  1999.                     m_Config.nWeaponSlots[3] = (DBYTE)b2cFile.dwWeap3;
  2000.                     m_Config.nWeaponSlots[4] = (DBYTE)b2cFile.dwWeap4;
  2001.                     m_Config.nWeaponSlots[5] = (DBYTE)b2cFile.dwWeap5;
  2002.                     m_Config.nWeaponSlots[6] = (DBYTE)b2cFile.dwWeap6;
  2003.                     m_Config.nWeaponSlots[7] = (DBYTE)b2cFile.dwWeap7;
  2004.                     m_Config.nWeaponSlots[8] = (DBYTE)b2cFile.dwWeap8;
  2005.                     m_Config.nWeaponSlots[9] = (DBYTE)b2cFile.dwWeap9;
  2006.                 }
  2007.                 else
  2008.                 {
  2009.                     // first gun is the beretta
  2010.                     m_Config.nWeaponSlots[1] = WEAP_BERETTA;
  2011.                     m_Config.nWeaponSlots[2] = WEAP_NONE;
  2012.                     m_Config.nWeaponSlots[3] = WEAP_NONE;
  2013.                     m_Config.nWeaponSlots[4] = WEAP_NONE;
  2014.                     m_Config.nWeaponSlots[5] = WEAP_NONE;
  2015.                     m_Config.nWeaponSlots[6] = WEAP_NONE;
  2016.                     m_Config.nWeaponSlots[7] = WEAP_NONE;
  2017.                     m_Config.nWeaponSlots[8] = WEAP_NONE;
  2018.                     m_Config.nWeaponSlots[9] = WEAP_NONE;
  2019.                     hstrName = pClientDE->CreateString(m_Config.szName);
  2020.                 }
  2021.                 if (!hstrName) return;
  2022.  
  2023.                 pClientDE->WriteToMessageHString(hMsg, hstrName);
  2024.                 pClientDE->FreeString(hstrName);
  2025.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nCharacter);
  2026.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nSkin);
  2027.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nStrength);
  2028.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nSpeed);
  2029.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nResistance);
  2030.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nMagic);
  2031.  
  2032. //                for(i = 0; i < 3; i++)
  2033. //                    pClientDE->WriteToMessageByte(hMsg, m_Config.nBindingSlots[i]);
  2034.                 for (i=1;i<SLOTCOUNT_WEAPONS;i++)    // Skip slot 0, it's melee
  2035.                     pClientDE->WriteToMessageByte(hMsg, m_Config.nWeaponSlots[i]);
  2036. /*                for (i=0;i<INV_LASTINVITEM;i++)
  2037.                     pClientDE->WriteToMessageByte(hMsg, m_Config.nItemSlots[i]);
  2038.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nProximityBombs);
  2039.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nRemoteBombs);
  2040.                 pClientDE->WriteToMessageByte(hMsg, m_Config.nTimeBombs);
  2041. //                for (i=0;i<6;i++)
  2042. //                    pClientDE->WriteToMessageByte(hMsg, m_Config.nSpellSlots[i]);
  2043. */
  2044.             }
  2045.             break;
  2046.     }
  2047.  
  2048.     // Finish it off..
  2049.     pClientDE->EndMessage(hMsg);
  2050. }
  2051.  
  2052.  
  2053. // ----------------------------------------------------------------------- //
  2054. //
  2055. //    ROUTINE:    CBloodClientShell::UpdateSoundReverb
  2056. //
  2057. //    PURPOSE:    Update the reverb info
  2058. //
  2059. // ----------------------------------------------------------------------- //
  2060. void CBloodClientShell::UpdateSoundReverb( )
  2061. {
  2062.     DVector vPlayerDims;
  2063.     ClientIntersectInfo info;
  2064.     ClientIntersectQuery query;
  2065.     DVector vPos[6], vSegs[6];
  2066.     int i;
  2067.     float fVolume, fReverbLevel;
  2068.     DBOOL bOpen;
  2069.     HLOCALOBJ hPlayerObj;
  2070.     ReverbProperties reverbProperties;
  2071.     HCONSOLEVAR hVar;
  2072.  
  2073.     if( !m_bUseReverb )
  2074.         return;
  2075.  
  2076.     hPlayerObj = g_pClientDE->GetClientObject();
  2077.     if( !hPlayerObj )
  2078.         return;
  2079.  
  2080.     hVar = g_pClientDE->GetConsoleVar( "ReverbLevel" );
  2081.     if( hVar )
  2082.     {
  2083.         fReverbLevel = g_pClientDE->GetVarValueFloat( hVar );
  2084.     }
  2085.     else
  2086.         fReverbLevel = 1.0f;
  2087.  
  2088.     // Check if reverb was off and is still off
  2089.     if( fReverbLevel < 0.001f && m_fReverbLevel < 0.001f )
  2090.         return;
  2091.  
  2092.     m_fReverbLevel = fReverbLevel;
  2093.  
  2094.     // Check if it's time yet
  2095.     if( g_pClientDE->GetTime( ) < m_fNextSoundReverbTime )
  2096.         return;
  2097.  
  2098.     // Update timer
  2099.     m_fNextSoundReverbTime = g_pClientDE->GetTime( ) + SOUND_REVERB_UPDATE_PERIOD;
  2100.  
  2101.     HOBJECT hFilterList[] = {hPlayerObj, m_pMoveMgr->GetObject(), DNULL};
  2102.  
  2103.     memset( &query, 0, sizeof( query ));
  2104.     query.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
  2105.     query.m_FilterFn = ObjListFilterFn;
  2106.     query.m_pUserData = hFilterList;
  2107.  
  2108.     g_pClientDE->GetObjectPos( hPlayerObj, &query.m_From );
  2109.     g_pClientDE->Physics( )->GetObjectDims( hPlayerObj, &vPlayerDims );
  2110.  
  2111.     // Player must move at least 2x his dims mag before reverb is checked again.
  2112.     if( VEC_DISTSQR( query.m_From, m_vLastReverbPos ) < 4 * VEC_MAGSQR( vPlayerDims ))
  2113.         return;
  2114.  
  2115.     VEC_COPY( m_vLastReverbPos, query.m_From );
  2116.  
  2117.     VEC_SET( vSegs[0], query.m_From.x + 2000.0f,    query.m_From.y,                query.m_From.z );
  2118.     VEC_SET( vSegs[1], query.m_From.x - 2000.0f,    query.m_From.y,                query.m_From.z );
  2119.     VEC_SET( vSegs[2], query.m_From.x,                query.m_From.y + 2000.0f,    query.m_From.z );
  2120.     VEC_SET( vSegs[3], query.m_From.x,                query.m_From.y - 2000.0f,    query.m_From.z );
  2121.     VEC_SET( vSegs[4], query.m_From.x,                query.m_From.y,                query.m_From.z + 2000.0f );
  2122.     VEC_SET( vSegs[5], query.m_From.x,                query.m_From.y,                query.m_From.z - 2000.0f );
  2123.  
  2124.     bOpen = DFALSE;
  2125.     for( i = 0; i < 6; i++ )
  2126.     {
  2127.         VEC_COPY( query.m_To, vSegs[i] );
  2128.  
  2129.         if( g_pClientDE->IntersectSegment( &query, &info ))
  2130.         {
  2131.             VEC_COPY( vPos[i], info.m_Point );
  2132.             if( info.m_SurfaceFlags == SURFTYPE_SKY )
  2133.             {
  2134.                 bOpen = DTRUE;
  2135.             }
  2136.         }
  2137.         else
  2138.         {
  2139.             VEC_COPY( vPos[i], vSegs[i] );
  2140.             bOpen = DTRUE;
  2141.         }
  2142.     }
  2143.  
  2144.     fVolume = VEC_DIST( vPos[0], vPos[1] );
  2145.     fVolume *= VEC_DIST( vPos[2], vPos[3] );
  2146.     fVolume *= VEC_DIST( vPos[4], vPos[5] );
  2147.  
  2148.     // Use room types that are not completely enclosed rooms
  2149.     if( bOpen )
  2150.     {
  2151.         if( fVolume < 100.0f*100.0f*100.0f )
  2152.         {
  2153.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_SEWERPIPE;
  2154.             reverbProperties.m_fReflectTime        = 0.005f;
  2155.             reverbProperties.m_fDecayTime        = 1.493f;
  2156.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2157.         }
  2158.         else if( fVolume < 500.0f*500.0f*500.0f )
  2159.         {
  2160.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_PLAIN;
  2161.             reverbProperties.m_fReflectTime        = 0.005f;
  2162.             reverbProperties.m_fDecayTime        = 1.493f;
  2163.             reverbProperties.m_fVolume            = 0.2f * m_fReverbLevel;
  2164.         }
  2165.         else if( fVolume < 1000.0f*1000.0f*1000.0f )
  2166.         {
  2167.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_ARENA;
  2168.             reverbProperties.m_fReflectTime        = 0.01f;
  2169.             reverbProperties.m_fDecayTime        = 4.236f;
  2170.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2171.         }
  2172.         else
  2173.         {
  2174.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_MOUNTAINS;
  2175.             reverbProperties.m_fReflectTime        = 0.0f;
  2176.             reverbProperties.m_fDecayTime        = 3.0f;
  2177.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2178.         }
  2179.     } 
  2180.     // Use room types that are enclosed rooms
  2181.     else
  2182.     {
  2183.         if( fVolume < 100.0f*100.0f*100.0f )
  2184.         {
  2185.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_STONEROOM;
  2186.             reverbProperties.m_fReflectTime        = 0.005f;
  2187.             reverbProperties.m_fDecayTime        = 0.6f;
  2188.             reverbProperties.m_fVolume            = 0.3f * m_fReverbLevel;
  2189.         }
  2190.         else if( fVolume < 500.0f*500.0f*500.0f )
  2191.         {
  2192.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_HALLWAY;
  2193.             reverbProperties.m_fReflectTime        = 0.01f;
  2194.             reverbProperties.m_fDecayTime        = 1.3f;
  2195.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2196.         }
  2197.         else if( fVolume < 1500.0f*1500.0f*1500.0f )
  2198.         {
  2199.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_CONCERTHALL;
  2200.             reverbProperties.m_fReflectTime        = 0.02f;
  2201.             reverbProperties.m_fDecayTime        = 2.2f;
  2202.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2203.         }
  2204.         else
  2205.         {
  2206.             reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_AUDITORIUM;
  2207.             reverbProperties.m_fReflectTime        = 0.02f;
  2208.             reverbProperties.m_fDecayTime        = 3.5f;
  2209.             reverbProperties.m_fVolume            = 0.1f * m_fReverbLevel;
  2210.         }
  2211.     }
  2212.  
  2213.     // Override to water if in it.
  2214.     if( IsLiquid( m_eCurContainerCode ))
  2215.         reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_UNDERWATER;
  2216.  
  2217.     reverbProperties.m_dwParams = REVERBPARAM_VOLUME | REVERBPARAM_ACOUSTICS | REVERBPARAM_REFLECTTIME | REVERBPARAM_DECAYTIME;
  2218.     g_pClientDE->SetReverbProperties( &reverbProperties );
  2219.  
  2220. }
  2221.  
  2222.  
  2223. // --------------------------------------------------------------------------- //
  2224. //
  2225. //    ROUTINE:    CBloodClientShell::UpdateCamera()
  2226. //
  2227. //    PURPOSE:    Updates the camera position and status
  2228. //
  2229. // --------------------------------------------------------------------------- //
  2230. void CBloodClientShell::UpdateCamera()
  2231. {
  2232.     CClientDE* pClientDE = GetClientDE();
  2233.     if (!pClientDE) return;
  2234.  
  2235.     HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  2236.     if (!hPlayerObj || !m_hCamera) return;
  2237.  
  2238.     if (!m_bHandledStartup)
  2239.     {
  2240.         m_bRenderCamera = DTRUE;
  2241. //        pClientDE->SetCameraZOrder(m_hCamera, 0);  // Okay, we can render now
  2242.         m_bHandledStartup = DTRUE;
  2243.     }
  2244.  
  2245.     // Update the player camera...
  2246.  
  2247.     if (!UpdatePlayerCamera()) return;
  2248.  
  2249.  
  2250.     m_pExternalCamera = DNULL;
  2251.  
  2252.     // See if we should use a cutscene camera...
  2253.  
  2254.     if (!m_hSeeingEyeObj && !m_hOrbObj)
  2255.     {
  2256.         CSpecialFXList* pCameraList = m_sfxMgr.GetCameraFXList();
  2257.         if (pCameraList)
  2258.         {
  2259.             int nNumCameras = pCameraList->GetNumItems();
  2260.  
  2261.             for (int i=0; i < nNumCameras; i++)
  2262.             {
  2263.                 CCameraFX* pCameraFX = (CCameraFX*)(*pCameraList)[i];
  2264.                 if (!pCameraFX) continue;
  2265.  
  2266.                 if ( HOBJECT hObj = pCameraFX->GetServerObj() )
  2267.                 {
  2268.                     DDWORD dwUsrFlags;
  2269.                     pClientDE->GetObjectUserFlags(hObj, &dwUsrFlags);
  2270.                     
  2271.                     // USRFLG_VISIBLE means the camera is active
  2272.                     if (dwUsrFlags & USRFLG_VISIBLE)
  2273.                     {
  2274.                         m_pExternalCamera = pCameraFX;
  2275.                         break;
  2276.                     }
  2277.                 }
  2278.             }
  2279.         }
  2280.     }
  2281.  
  2282.     if ((m_pExternalCamera && !m_pExternalCamera->GetHidePlayer()) || m_hSeeingEyeObj || m_hOrbObj)
  2283.     {
  2284.         ShowPlayer(DTRUE);
  2285.     }
  2286.     else
  2287.     {
  2288.         if (m_bDead && m_bDeadNoHide)
  2289.         {
  2290.             ShowPlayer(TRUE);
  2291.         }
  2292.         else
  2293.         {
  2294.             ShowPlayer((m_bDead) ? DFALSE : !m_playerCamera.IsFirstPerson());
  2295.         }
  2296.     }
  2297.  
  2298.     CalculateCameraRotation();
  2299.     UpdateCameraPosition();
  2300.     UpdateCameraRotation();
  2301.  
  2302.     // Adjust camera for current resolution
  2303.     SetCameraStuff(hPlayerObj, m_hCamera);
  2304. }
  2305.  
  2306.  
  2307.  
  2308. // --------------------------------------------------------------------------- //
  2309. //
  2310. //    ROUTINE:    CBloodClientShell::FirstUpdate()
  2311. //
  2312. //    PURPOSE:    Special stuff to do on the first update after entering a world.
  2313. //
  2314. // --------------------------------------------------------------------------- //
  2315. void CBloodClientShell::FirstUpdate()
  2316. {
  2317.     CClientDE* pClientDE = GetClientDE();
  2318.     if (!pClientDE) return;
  2319.  
  2320.     char buf[100];
  2321.     char *pStrParam;
  2322.  
  2323.     ShowPlayer(m_b3rdPerson ? DTRUE : DFALSE);
  2324.  
  2325.     // Check for add-on special case stuff...
  2326.  
  2327. #ifdef _ADDON
  2328.     if (g_bPlayerInvReset)
  2329.     {
  2330.         ResetPlayerInventory();
  2331.         g_bPlayerInvReset = DFALSE;
  2332.     }
  2333. #endif
  2334.     
  2335.     // Display the world name if any
  2336. //    if (pStrParam = pClientDE->GetServerConVarValueString("WorldName"))
  2337. //    {
  2338. //        CSPrint("Entering %s", pStrParam);
  2339. //    }
  2340.  
  2341.     // Set the FarZ setting for the world...
  2342.     DFLOAT fVal = pClientDE->GetServerConVarValueFloat("FarZ");
  2343.  
  2344.     if (fVal > 0.0f)
  2345.     {
  2346.         sprintf(buf, "FarZ %d", (int)fVal);
  2347.         pClientDE->RunConsoleString(buf);
  2348.     }
  2349.  
  2350.     ResetGlobalFog();
  2351.  
  2352.     // Set up the environment map texture...
  2353.  
  2354.     pStrParam = pClientDE->GetServerConVarValueString("EnvironmentMap");
  2355.     if (pStrParam && (m_nGlobalDetail == DETAIL_HIGH))
  2356.     {
  2357.         sprintf(buf, "EnvMap %s", pStrParam);
  2358.         pClientDE->RunConsoleString(buf);
  2359.         pClientDE->RunConsoleString("EnvMapEnable 1");
  2360.     }
  2361.     else
  2362.     {
  2363.         pClientDE->RunConsoleString("EnvMapEnable 0");
  2364.     }
  2365.  
  2366.     pClientDE->RunConsoleString("ModelWarble 0");
  2367.     pClientDE->RunConsoleString("WarbleSpeed 15");
  2368.     pClientDE->RunConsoleString("WarbleScale .95");
  2369.  
  2370.     // Sky panning...
  2371.  
  2372.     m_bPanSky = (DBOOL) pClientDE->GetServerConVarValueFloat("PanSky");
  2373.     m_fPanSkyOffsetX = pClientDE->GetServerConVarValueFloat("PanSkyOffsetX");
  2374.     m_fPanSkyOffsetZ = pClientDE->GetServerConVarValueFloat("PanSkyOffsetZ");
  2375.     m_fPanSkyScaleX = pClientDE->GetServerConVarValueFloat("PanSkyScaleX");
  2376.     m_fPanSkyScaleZ = pClientDE->GetServerConVarValueFloat("PanSkyScaleZ");
  2377.     pStrParam  = pClientDE->GetServerConVarValueString("PanSkyTexture");
  2378.  
  2379.     if (m_bPanSky)
  2380.     {
  2381.         pClientDE->SetGlobalPanTexture(GLOBALPAN_SKYSHADOW, pStrParam);
  2382.     }
  2383.  
  2384.     // Initialize the music playlists...
  2385.  
  2386.     if ( m_Music.IsInitialized( ) )
  2387.     {
  2388. //        CMusic::EMusicLevel level;
  2389. //        level = m_Music.GetMusicLevel( );
  2390. /*        m_Music.TermPlayLists();
  2391.         m_Music.InitPlayLists( );
  2392.         if ( !m_Music.UsingIMA( ))
  2393.             m_Music.PlayCDList( );
  2394.         else
  2395.             m_Music.PlayMusicLevel( m_eMusicLevel );
  2396. */
  2397.     }
  2398.  
  2399.     // Set up the soft renderer sky map...
  2400.  
  2401.     char* pSoftSky = pClientDE->GetServerConVarValueString("SoftSky");
  2402.     if (pSoftSky)
  2403.     {
  2404.         sprintf(buf, "SoftSky %s", pSoftSky);
  2405.         pClientDE->RunConsoleString(buf);
  2406.     }
  2407.  
  2408.     // Send initial update message
  2409.     SendPlayerUpdateMessage(DTRUE);
  2410.  
  2411.     m_bFirstUpdate = DFALSE;
  2412. }
  2413.  
  2414.  
  2415. // --------------------------------------------------------------------------- //
  2416. //
  2417. //    ROUTINE:    CBloodClientShell::ResetGlobalFog
  2418. //
  2419. //    PURPOSE:    Reset the global fog value...
  2420. //
  2421. // --------------------------------------------------------------------------- //
  2422.  
  2423. void CBloodClientShell::ResetGlobalFog()
  2424. {
  2425.     CClientDE* pClientDE = GetClientDE();
  2426.     if (!pClientDE) return;
  2427.  
  2428.     DFLOAT fVal = pClientDE->GetServerConVarValueFloat("FogEnable");
  2429.     
  2430.     char buf[30];
  2431.     sprintf(buf, "FogEnable %d", (int)fVal);
  2432.     pClientDE->RunConsoleString(buf);
  2433.     if (fVal)
  2434.     {
  2435.         fVal = pClientDE->GetServerConVarValueFloat("FogNearZ");
  2436.         sprintf(buf, "FogNearZ %d", (int)fVal);
  2437.         pClientDE->RunConsoleString(buf);
  2438.  
  2439.         fVal = pClientDE->GetServerConVarValueFloat("FogFarZ");
  2440.         sprintf(buf, "FogFarZ %d", (int)fVal);
  2441.         pClientDE->RunConsoleString(buf);
  2442.  
  2443.         fVal = pClientDE->GetServerConVarValueFloat("FogR");
  2444.         sprintf(buf, "FogR %d", (int)fVal);
  2445.         pClientDE->RunConsoleString(buf);
  2446.  
  2447.         fVal = pClientDE->GetServerConVarValueFloat("FogG");
  2448.         sprintf(buf, "FogG %d", (int)fVal);
  2449.         pClientDE->RunConsoleString(buf);
  2450.  
  2451.         fVal = pClientDE->GetServerConVarValueFloat("FogB");
  2452.         sprintf(buf, "FogB %d", (int)fVal);
  2453.         pClientDE->RunConsoleString(buf);
  2454.     }
  2455.  
  2456.     // ModelAdd
  2457.     DFLOAT fR, fG, fB;
  2458.     fR = pClientDE->GetServerConVarValueFloat("ModelAddR");
  2459.     fG = pClientDE->GetServerConVarValueFloat("ModelAddG");
  2460.     fB = pClientDE->GetServerConVarValueFloat("ModelAddB");
  2461.     sprintf(buf, "ModelAdd %d %d %d", (int)fR, (int)fG, (int)fB);
  2462.     pClientDE->RunConsoleString(buf);
  2463.  
  2464.     // ModelDirAdd
  2465.     fR = pClientDE->GetServerConVarValueFloat("ModelDirAddR");
  2466.     fG = pClientDE->GetServerConVarValueFloat("ModelDirAddG");
  2467.     fB = pClientDE->GetServerConVarValueFloat("ModelDirAddB");
  2468.     sprintf(buf, "ModelDirAdd %d %d %d", (int)fR, (int)fG, (int)fB);
  2469.     pClientDE->RunConsoleString(buf);
  2470.     
  2471.     fVal = pClientDE->GetServerConVarValueFloat("SkyFog");
  2472.     sprintf(buf, "SkyFog %d", (int)fVal);
  2473.     pClientDE->RunConsoleString(buf);
  2474.     if (fVal)
  2475.     {
  2476.         fVal = pClientDE->GetServerConVarValueFloat("SkyFogNearZ");
  2477.         sprintf(buf, "SkyFogNearZ %d", (int)fVal);
  2478.         pClientDE->RunConsoleString(buf);
  2479.  
  2480.         fVal = pClientDE->GetServerConVarValueFloat("SkyFogFarZ");
  2481.         sprintf(buf, "SkyFogFarZ %d", (int)fVal);
  2482.         pClientDE->RunConsoleString(buf);
  2483.     }
  2484. }
  2485.  
  2486.  
  2487. // --------------------------------------------------------------------------- //
  2488. //
  2489. //    ROUTINE:    CBloodClientShell::Update()
  2490. //
  2491. //    PURPOSE:    the client shell update function.
  2492. //
  2493. // --------------------------------------------------------------------------- //
  2494. void CBloodClientShell::Update()
  2495. {
  2496.     HLOCALOBJ hPlayerObj;
  2497.  
  2498.     CClientDE* pClientDE = GetClientDE();
  2499.  
  2500.     m_pMoveMgr->Update();
  2501.  
  2502.     UpdateSoundReverb( );
  2503.     
  2504.     switch (GetGameState())
  2505.     {
  2506.         case GS_PLAYING:
  2507.         case GS_MENUANIM:
  2508.         {
  2509.             if (!m_bInWorld || !pClientDE) 
  2510.                 return;
  2511.  
  2512.             if (g_bLevelChangeNoUpdate)
  2513.                 return;
  2514.  
  2515.             // Make sure server is still running
  2516.             if (!pClientDE->IsConnected())
  2517.             {
  2518.                 HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_SHUTDOWN);
  2519.                 CSPrint(pClientDE->GetStringData(szErrorStr));
  2520.                 pClientDE->FreeString(szErrorStr);
  2521.                 m_bInWorld = DFALSE;
  2522.                 return;
  2523.             }
  2524.  
  2525.             hPlayerObj = pClientDE->GetClientObject();
  2526.  
  2527.             if (!hPlayerObj)
  2528.                 return;
  2529.  
  2530.             if (m_bFirstUpdate)
  2531.             {
  2532.                 FirstUpdate();
  2533.             }
  2534.  
  2535.             // Update weapons firing..
  2536.             HandleFiring();
  2537.  
  2538.             // Initialize cameraadd and lightscale..
  2539.  
  2540.             VEC_SET(m_vLightScale, 1.0f, 1.0f, 1.0f);
  2541.             VEC_SET(m_vCameraAdd, 0.0f, 0.0f, 0.0f);
  2542.  
  2543.             // Update sky panning
  2544.  
  2545.             if (m_bPanSky)
  2546.             {
  2547.                 DFLOAT fFrameTime = pClientDE->GetFrameTime();
  2548.  
  2549.                 m_fCurSkyXOffset += fFrameTime * m_fPanSkyOffsetX;
  2550.                 m_fCurSkyZOffset += fFrameTime * m_fPanSkyOffsetZ;
  2551.  
  2552.                 pClientDE->SetGlobalPanInfo(GLOBALPAN_SKYSHADOW, m_fCurSkyXOffset, m_fCurSkyZOffset, m_fPanSkyScaleX, m_fPanSkyScaleZ);
  2553.             }
  2554.  
  2555.             // Update the camera
  2556.             UpdateCamera();
  2557.  
  2558.             // Update the screen shake
  2559.             if (m_bShakeScreen)
  2560.                 UpdateScreenShake();
  2561.  
  2562.             // Update the screen flash
  2563.             if (m_bFlashScreen)
  2564.                 UpdateScreenFlash();
  2565.  
  2566.             // Update container effects...
  2567.             UpdateContainerFX();
  2568.  
  2569.             if(m_pCreature && m_pCreature->GetType() == SMSG_THIEF_ATTACH || IsWonky())
  2570.             {
  2571.                 // Update the wonkyvision timer.
  2572.                 if (IsWonky())
  2573.                 {
  2574.                     m_fWonkyTime -= pClientDE->GetFrameTime();
  2575.                     if (m_fWonkyTime <= 0)
  2576.                     {
  2577.                         EndWonkyVision();
  2578.                     }
  2579.                 }
  2580.  
  2581.                 UpdateWonkyVision();
  2582.             }
  2583.             else
  2584.             {
  2585.                 pClientDE->RunConsoleString("ModelWarble 0");
  2586.  
  2587.                 m_fOffsetY = 0.0f;
  2588.                 m_fOffsetX = 0.0f;
  2589.                 m_fOffsetRot = 0.0f;
  2590.             }
  2591.  
  2592.             // Update night goggles sounds...
  2593.             if( m_bNightGogglesActive )
  2594.             {
  2595.                 // Start the sound...
  2596.                 if( !m_hNightGogglesSound )
  2597.                 {
  2598.                     m_hNightGogglesSound = PlaySoundLocal( "sounds\\powerups\\nightgogglesloop1.wav", 
  2599.                         SOUNDPRIORITY_PLAYER_LOW, DTRUE, DTRUE );
  2600.                 }
  2601.             }
  2602.             else
  2603.             {
  2604.                 // Kill the sound...
  2605.                 if( m_hNightGogglesSound )
  2606.                 {
  2607.                     g_pClientDE->KillSound( m_hNightGogglesSound );
  2608.                     m_hNightGogglesSound = DNULL;
  2609.                 }
  2610.             }
  2611.  
  2612.  
  2613.             SetPhysicsStateTimeStep(&g_normalPhysicsState, pClientDE->GetFrameTime());
  2614.             SetPhysicsStateTimeStep(&g_waterPhysicsState, pClientDE->GetFrameTime());
  2615.  
  2616.  
  2617.             // Update any client-side special effects...
  2618.             m_sfxMgr.UpdateSpecialFX();
  2619.  
  2620.  
  2621.             // Check for Burn
  2622.  
  2623.  
  2624.             // Set the light scale
  2625.             if (m_bBlind)
  2626.             {
  2627.                 if (pClientDE->GetTime() > m_fBlindTime)
  2628.                     m_bBlind = DFALSE;
  2629.             }
  2630.  
  2631.             // Set the light scale depending on the state
  2632.             DVector vLightScale;
  2633.             if (m_bBlind)
  2634.             {
  2635.                 VEC_SET(vLightScale, 0.0f, 0.0f, 0.0f)
  2636.             }
  2637.             else if (m_bFadeIn)    // 4 second fade-in
  2638.             {
  2639.                 m_fFadeVal += 100 * pClientDE->GetFrameTime();
  2640.                 if (m_fFadeVal > 255) 
  2641.                 {
  2642.                     m_fFadeVal = 255;
  2643.                     m_bFadeIn = DFALSE;
  2644.                 }
  2645.                 DFLOAT fScale = m_fFadeVal / 255.0f;
  2646.                 VEC_SET(vLightScale, fScale, fScale, fScale);
  2647.             }
  2648.             else if (m_bFadeOut) // 4 second fade-out
  2649.             {
  2650.                 m_fFadeVal -= 100 * pClientDE->GetFrameTime();
  2651.                 if (m_fFadeVal < 0) 
  2652.                 {
  2653.                     m_fFadeVal = 0;
  2654.                 }
  2655.                 DFLOAT fScale = m_fFadeVal / 255.0f;
  2656.                 VEC_SET(vLightScale, fScale, fScale, fScale);
  2657.             }
  2658. //            else if (m_bStoneView)
  2659. //            {
  2660. //                VEC_SET(vLightScale, 0.0f, 0.0f, 1.0f)
  2661. //            }
  2662.             else if (m_hSeeingEyeObj)
  2663.             {
  2664.                 VEC_SET(vLightScale, 1.0f, 0.0f, 0.5f)
  2665.             }
  2666.             else if(m_pCreature)
  2667.             {
  2668.                 VEC_COPY(vLightScale, m_pCreature->GetLightScale());
  2669.             }
  2670.             else if(m_bNightGogglesActive)
  2671.             {
  2672.                 VEC_SET(vLightScale, 0.1f, 1.0f, 0.1f);
  2673.             }
  2674.             else    // Default
  2675.             {
  2676.                 VEC_COPY(vLightScale, m_vLightScale);
  2677.             }
  2678.  
  2679.             pClientDE->SetGlobalLightScale(&vLightScale);
  2680.             pClientDE->SetCameraLightAdd(m_hCamera, &m_vCameraAdd);
  2681.  
  2682.             // Update the server with player info
  2683.             SendPlayerUpdateMessage(DFALSE);
  2684.  
  2685.             // Roll the credits if necessary
  2686.             if (m_bRollCredits)
  2687.             {
  2688.                 if (m_Credits.IsInited())
  2689.                 {
  2690.                     m_Credits.Update();
  2691.                 }
  2692.                 else
  2693.                 {
  2694.                     m_Credits.Init(pClientDE, this, CM_CREDITS, DFALSE);
  2695.                 }
  2696.             }
  2697.  
  2698.             // Zoom camera out
  2699.             if (m_CheatMgr.IsCheatActive(CHEAT_CHASEVIEW) || g_bLevelChange3rdPersonCam)
  2700.             {
  2701.                 if (!m_b3rdPerson)
  2702.                     Set3rdPersonCamera(DTRUE);
  2703.             }
  2704.             // Zoom camera in
  2705.             else
  2706.             {
  2707.                 if (m_b3rdPerson)
  2708.                     Set3rdPersonCamera(DFALSE);
  2709.             }
  2710.  
  2711.             break;
  2712.         }
  2713.  
  2714.         // Nothing to do if we're in menu mode..
  2715.         case GS_MENU:    
  2716.             break;
  2717.  
  2718.         case GS_LOADINGLEVEL:
  2719.         case GS_MPLOADINGLEVEL:
  2720.         case GS_WAITING:
  2721.             break;
  2722.  
  2723.         case GS_CREDITS :
  2724.         {
  2725.             UpdateCredits();
  2726.             return;
  2727.         }
  2728.  
  2729.         case GS_MOVIES:
  2730.         {
  2731.             UpdateMoviesState();
  2732.             return;
  2733.         }
  2734.  
  2735.         case GS_SPLASH:
  2736.         {
  2737.             Splash_Update();
  2738.             return;
  2739.         }
  2740.  
  2741.         break;
  2742.     }
  2743.  
  2744.     pClientDE->ClearScreen(DNULL, CLEARSCREEN_SCREEN | CLEARSCREEN_RENDER);
  2745.     if (m_bRenderCamera)
  2746.     {
  2747.         pClientDE->Start3D();
  2748.         if( pClientDE->GetClientObject())
  2749.             pClientDE->ProcessAttachments(pClientDE->GetClientObject());    // [blg]
  2750.         pClientDE->RenderCamera(m_hCamera);
  2751.         if (m_bRollCredits && m_Credits.IsInited()) m_Credits.Update();    // [blg]
  2752.         pClientDE->End3D();
  2753.     }
  2754. }
  2755.  
  2756.  
  2757. // ----------------------------------------------------------------------- //
  2758. //
  2759. //    ROUTINE:    CBloodClientShell::UpdateCredits()
  2760. //
  2761. //    PURPOSE:    Update the credits
  2762. //
  2763. // ----------------------------------------------------------------------- //
  2764.  
  2765. void CBloodClientShell::UpdateCredits()
  2766. {
  2767.     CClientDE* pClientDE = GetClientDE();
  2768.     if (!pClientDE) return;
  2769.  
  2770.     pClientDE->Start3D();
  2771.     m_Credits.Update();
  2772.     pClientDE->End3D();
  2773. }
  2774.  
  2775.  
  2776. // --------------------------------------------------------------------------- //
  2777. //
  2778. //    ROUTINE:    CBloodClientShell::OnObjectMove()
  2779. //
  2780. //    PURPOSE:    
  2781. //
  2782. // --------------------------------------------------------------------------- //
  2783. DRESULT CBloodClientShell::OnObjectMove(HOBJECT hObj, DBOOL bTeleport, DVector *pPos)
  2784. {
  2785.     m_pMoveMgr->OnObjectMove(hObj, bTeleport, pPos);
  2786.     return LT_OK;
  2787. }
  2788.  
  2789. DRESULT CBloodClientShell::OnObjectRotate(HOBJECT hObj, DBOOL bTeleport, DRotation *pNewRot)
  2790. {
  2791.     return m_pMoveMgr->OnObjectRotate(hObj, bTeleport, pNewRot);
  2792. }
  2793.  
  2794.  
  2795.  
  2796. // --------------------------------------------------------------------------- //
  2797. //
  2798. //    ROUTINE:    CBloodClientShell::PreLoadWorld()
  2799. //
  2800. //    PURPOSE:    Display a loading screen right before loading the next world.
  2801. //
  2802. // --------------------------------------------------------------------------- //
  2803. void CBloodClientShell::PreLoadWorld(char *pWorldName)
  2804. {
  2805.     CClientDE* pClientDE = GetClientDE();
  2806.  
  2807.     DrawLoadingScreen();
  2808.     pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE);
  2809.     DrawLoadingScreen();
  2810.  
  2811.     g_bLevelChangeNoUpdate = DFALSE;
  2812.  
  2813.  
  2814.     // Re-Init the team manager...
  2815.  
  2816.     m_TeamMgr.Term();
  2817.     m_TeamMgr.Init();
  2818.  
  2819.     HSTRING hTeam1String = pClientDE->FormatString(IDS_TEAM1NAME);
  2820.     HSTRING hTeam2String = pClientDE->FormatString(IDS_TEAM2NAME);
  2821.  
  2822.     if (hTeam1String)
  2823.     {
  2824.         m_TeamMgr.AddTeam(TEAM_1, pClientDE->GetStringData(hTeam1String));
  2825.     }
  2826.     else
  2827.     {
  2828.         m_TeamMgr.AddTeam(TEAM_1, "Team Blue");
  2829.     }
  2830.  
  2831.     if (hTeam2String)
  2832.     {
  2833.         m_TeamMgr.AddTeam(TEAM_2, pClientDE->GetStringData(hTeam2String));
  2834.     }
  2835.     else
  2836.     {
  2837.         m_TeamMgr.AddTeam(TEAM_2, "Team Blue");
  2838.     }
  2839.  
  2840.     if (hTeam1String) pClientDE->FreeString(hTeam1String);
  2841.     if (hTeam2String) pClientDE->FreeString(hTeam2String);
  2842.  
  2843.  
  2844.     // Stop any voice sounds...
  2845.  
  2846.     GetVoiceMgr()->StopAll();
  2847.  
  2848.  
  2849.     // Check if we should roll the credits on top of this world...
  2850.     strupr(pWorldName);
  2851.     m_bRollCredits = DFALSE;
  2852.  
  2853.     if (pWorldName)
  2854.     {
  2855.         if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"END") == 0 || _mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS\\END") == 0)
  2856.         {
  2857.             m_bRollCredits = DTRUE;
  2858.         }
  2859.  
  2860.         if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"CREDITS") == 0 || _mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS\\CREDITS") == 0)
  2861.         {
  2862.             m_bRollCredits = DTRUE;
  2863.         }
  2864.  
  2865. #ifdef _ADDON
  2866.         if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS_AO\\END") == 0)
  2867.         {
  2868.             m_bRollCredits = DTRUE;
  2869.         }
  2870.  
  2871.         if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS_AO\\CREDITS") == 0)
  2872.         {
  2873.             m_bRollCredits = DTRUE;
  2874.         }
  2875. #endif
  2876.  
  2877.     }
  2878.  
  2879.     m_Credits.Term();
  2880.  
  2881.  
  2882.     // Check if this is an add-on level that wants a character change...
  2883.  
  2884.     g_bPlayerInvReset = DFALSE;
  2885.  
  2886. #ifdef _ADDON
  2887.     char sUpr[256];
  2888.     strncpy(sUpr, pWorldName, 255);
  2889.     strupr(sUpr);
  2890.  
  2891.     if (strstr(sUpr, "_AO"))            // is this an add-on level?
  2892.     {
  2893.         if (strstr(sUpr, "_CC_C"))        // switch to caleb?
  2894.         {
  2895.             SetCharacterInfo(CHARACTER_CALEB, MULTIPLAY_SKIN_NORMAL);
  2896.             g_bPlayerInvReset = DTRUE;
  2897.         }
  2898.         else if (strstr(sUpr, "_CC_I"))    // switch to ishmael?
  2899.         {
  2900.             SetCharacterInfo(CHARACTER_ISHMAEL, MULTIPLAY_SKIN_NORMAL);
  2901.             g_bPlayerInvReset = DTRUE;
  2902.         }
  2903.         else if (strstr(sUpr, "_CC_O"))    // switch to ophelia?
  2904.         {
  2905.             SetCharacterInfo(CHARACTER_OPHELIA, MULTIPLAY_SKIN_NORMAL);
  2906.             g_bPlayerInvReset = DTRUE;
  2907.         }
  2908.         else if (strstr(sUpr, "_CC_G"))    // switch to gabby?
  2909.         {
  2910.             SetCharacterInfo(CHARACTER_GABREILLA, MULTIPLAY_SKIN_NORMAL);
  2911.             g_bPlayerInvReset = DTRUE;
  2912.         }
  2913.     }
  2914.  
  2915.     if (m_nLastLoadType == LOADTYPE_RESTORESAVE || m_nLastLoadType == LOADTYPE_RESTOREAUTOSAVE)
  2916.     {
  2917.         g_bPlayerInvReset = DFALSE;
  2918.     }
  2919.  
  2920.     if (strstr(sUpr, "ENDBOSS_CC_C"))    // check for final caleb nightmare level
  2921.     {
  2922.         g_bPlayerInvReset = DFALSE;
  2923.     }
  2924. #endif
  2925.  
  2926. }
  2927.  
  2928.  
  2929. // --------------------------------------------------------------------------- //
  2930. //
  2931. //    ROUTINE:    CBloodClientShell::PostUpdate()
  2932. //
  2933. //    PURPOSE:    Called after client object update functions.
  2934. //
  2935. // --------------------------------------------------------------------------- //
  2936. void CBloodClientShell::PostUpdate()
  2937. {
  2938.     CClientDE* pClientDE = GetClientDE();
  2939.  
  2940.     HSURFACE hScreen = pClientDE->GetScreenSurface();
  2941.  
  2942.     // Delete the loading screen if there is one.
  2943.     if (GetGameState() == GS_LOADINGLEVEL || GetGameState() == GS_MPLOADINGLEVEL || GetGameState() == GS_WAITING)
  2944.     {
  2945.         DrawLoadingScreen();
  2946.         pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE);
  2947.         return;
  2948.     }
  2949.     else if (m_hLoadingScreen)
  2950.     {
  2951.         pClientDE->DeleteSurface(m_hLoadingScreen);
  2952.         m_hLoadingScreen = DNULL;
  2953.         m_bPlayedWaitingSound = DFALSE;
  2954.     }
  2955.  
  2956.     if (GetGameState() == GS_MENU)
  2957.     {
  2958.         m_Menu.Draw();
  2959.     }
  2960.     else if (GetGameState() == GS_PLAYING)
  2961.     {
  2962.         if (g_bLevelChangeNoUpdate)
  2963.         {
  2964.             return;
  2965.         }
  2966.  
  2967.         m_MessageMgr.Draw();
  2968.         DBOOL bDraw = m_bDrawStatusBar && !(m_pExternalCamera);
  2969.         m_NewStatusBar.Draw(bDraw);
  2970.         m_CommLink.Draw(DTRUE);
  2971.     
  2972.         if (m_bDrawFragBar && IsMultiplayerGame())
  2973.         {
  2974.             m_FragInfo.Draw (DTRUE, DTRUE);
  2975.         }
  2976.  
  2977.         if (m_bShowCrosshair && !m_pExternalCamera && !m_bDead && !m_hSeeingEyeObj && !m_hOrbObj && !g_bLevelChange3rdPersonCam && !m_bDrawFragBar)
  2978.         {
  2979.             if(m_nLastCrosshair != m_nCrosshair)
  2980.             {
  2981.                 if(m_hCrosshair)    pClientDE->DeleteSurface(m_hCrosshair);
  2982.                 m_hCrosshair = 0;
  2983.                 m_nLastCrosshair = m_nCrosshair;
  2984.             }
  2985.  
  2986.             if (!m_hCrosshair)
  2987.             {
  2988.                 char    file[128];
  2989.  
  2990.                 if(m_nCrosshair < 10)
  2991.                     sprintf(file, "Interface/Crosshairs/Crosshair0%d.pcx", m_nCrosshair);
  2992.                 else
  2993.                     sprintf(file, "Interface/Crosshairs/Crosshair%d.pcx", m_nCrosshair);
  2994.  
  2995.                 m_hCrosshair = pClientDE->CreateSurfaceFromBitmap(file);
  2996.                 pClientDE->GetSurfaceDims (m_hCrosshair, &m_cxCrosshair, &m_cyCrosshair);
  2997.             }
  2998.  
  2999.             DBOOL bFullScreen = DFALSE;
  3000.             int nLeft = 0;
  3001.             int nTop = 0;
  3002.             int nRight = 0;
  3003.             int nBottom = 0;
  3004.             pClientDE->GetCameraRect (m_hCamera, &bFullScreen, &nLeft, &nTop, &nRight, &nBottom);
  3005.             if (bFullScreen)
  3006.             {
  3007.                 pClientDE->GetSurfaceDims (hScreen, &m_dwScreenWidth, &m_dwScreenHeight);
  3008.                 nRight = (int)m_dwScreenWidth;
  3009.                 nBottom = (int)m_dwScreenHeight;
  3010.             }
  3011.  
  3012.             int x = nLeft + (((nRight - nLeft) - m_cxCrosshair) >> 1);
  3013.             int y = nTop + (((nBottom - nTop) - m_cyCrosshair) >> 1);
  3014.  
  3015.             pClientDE->DrawSurfaceToSurfaceTransparent (hScreen, m_hCrosshair, NULL, x, y, NULL);
  3016.         }
  3017.     }
  3018.  
  3019.     // Draw the message box if it is up
  3020.     if (m_bInMessageBox)
  3021.     {
  3022.         m_messageBox.Render(hScreen);
  3023.     }
  3024.  
  3025. #ifdef BRANDED
  3026.     if (m_hBrandSurface && m_fBrandCounter > 0)
  3027.     {
  3028.         DrawBrandString(hScreen);
  3029.         m_fBrandCounter -= pClientDE->GetFrameTime();
  3030.     }
  3031. #endif
  3032.  
  3033.     pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE);
  3034. }
  3035.  
  3036.  
  3037. // --------------------------------------------------------------------------- //
  3038. //
  3039. //    ROUTINE:    CBloodClientShell::UpdateBob
  3040. //
  3041. //    PURPOSE:    Adjusts the head bobbing & swaying
  3042. //
  3043. // --------------------------------------------------------------------------- //
  3044. void CBloodClientShell::UpdateBob()
  3045. {
  3046.     DFLOAT    bobH;
  3047.     DFLOAT  bobV;
  3048.     DFLOAT  swayH;
  3049.     DFLOAT  swayV;
  3050.     DFLOAT    pace;
  3051.     DBOOL   bRunning;
  3052.     DFLOAT  moveDist;
  3053.  
  3054.     CClientDE* pClientDE = GetClientDE();
  3055.     if (!pClientDE) return;
  3056.     HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  3057.     if (!hPlayerObj) return;
  3058.  
  3059.     // Calculate velocities
  3060.     DVector vMyPos;
  3061.     pClientDE->GetObjectPos(hPlayerObj, &vMyPos);
  3062.     
  3063.     // Calculate Y velocity for camera dampening
  3064.     DFLOAT fVelY = (vMyPos.y - m_vMyLastPos.y) / (pClientDE->GetFrameTime() * 100.0f);
  3065.     CLIPLOWHIGH(fVelY, -20, 20);
  3066.  
  3067.     VEC_COPY(m_vMyLastPos, vMyPos);
  3068.  
  3069.     bRunning = (cdata.byFlags & CDATA_RUNLOCK || pClientDE->IsCommandOn(COMMAND_RUN));
  3070.     moveDist = (m_fVelMagnitude) * pClientDE->GetFrameTime();
  3071.  
  3072.     // Running
  3073.  
  3074.     if (bRunning)
  3075.     {
  3076.         pace = PIx2 * 0.5f;
  3077.         bobH = BOBH_WALKING / 500.0f;
  3078.         bobV = BOBV_WALKING / 500.0f;
  3079.         swayH = SWAYH_WALKING / 10000.0f;
  3080.         swayV = SWAYV_WALKING / 10000.0f;
  3081.     }
  3082.     else
  3083.     {
  3084.         pace = PIx2 * 0.25f;
  3085.         bobH = BOBH_WALKING / 500.0f;
  3086.         bobV = BOBV_WALKING / 500.0f;
  3087.         swayH = SWAYH_WALKING / 5000.0f;
  3088.         swayV = SWAYV_WALKING / 5000.0f;
  3089.     }
  3090.     
  3091.     m_fBobPhase += (pClientDE->GetFrameTime() * pace);
  3092.     if (m_fBobPhase > PIx2) m_fBobPhase -= PIx2;
  3093.  
  3094.     m_fSwayPhase += (pClientDE->GetFrameTime() * pace) / 2;
  3095.     if (m_fSwayPhase > PIx2) m_fSwayPhase -= PIx2;
  3096.  
  3097.     // decay the amplitude
  3098.     m_fBobAmp = m_fBobAmp - pClientDE->GetFrameTime() * 150;
  3099.     if (m_fBobAmp < 0) m_fBobAmp = 0;
  3100.  
  3101.     if (m_fBobAmp < 30)
  3102.     {
  3103.         m_fBobAmp += moveDist;
  3104.         if (m_fBobAmp > 30) m_fBobAmp = 30;
  3105.     }
  3106.  
  3107.     // Head bobbing
  3108.     m_fBobHeight = bobV * m_fBobAmp * (float)sin(m_fBobPhase * 2);
  3109.     m_fBobWidth  = bobH * m_fBobAmp * (float)sin(m_fBobPhase * 1 - (PI/4));
  3110.     m_fBobCant     = m_fBobWidth / 200.0f;
  3111.     // Weapon swaying
  3112.     m_fSwayHeight = -swayV * m_fBobAmp * (float)sin(m_fSwayPhase * 4) / 3;
  3113.     m_fSwayWidth = swayH * m_fBobAmp * (float)sin(m_fSwayPhase * 2 - (PI/3)) / 3;
  3114.  
  3115.     // Adjust camera velocity
  3116. #define kViewDamping    0.43f
  3117. #define kViewStiffnessA 0.625f  // return force when above goal y
  3118. #define kViewStiffnessB 0.112f  // return force when below goal y
  3119.  
  3120.     DFLOAT fLast = m_fViewYVel;
  3121.     m_fViewYVel = INTERPOLATE(m_fViewYVel, fVelY, kViewDamping);
  3122.     DFLOAT dz = m_fEyeLevel - m_fViewY;
  3123.     if ( dz < 0 )
  3124.         m_fViewYVel += dz * kViewStiffnessA;
  3125.     else
  3126.         m_fViewYVel += dz * kViewStiffnessB;
  3127.     if (fabs(m_fViewYVel) < 0.1f) m_fViewYVel = 0;
  3128.     m_fViewY += m_fViewYVel;
  3129.  
  3130. #define kWeapDamping    0.312f
  3131. #define kWeapStiffnessA 0.5f  // return force when above goal y
  3132. #define kWeapStiffnessB 0.047f // return force when below goal y
  3133.  
  3134.     m_fWeaponYVel = INTERPOLATE(m_fWeaponYVel, -(fVelY/80.0f), kWeapDamping);
  3135.     dz = -m_fWeaponY;
  3136.     if ( dz < 0 )
  3137.         m_fWeaponYVel += dz * kWeapStiffnessA;
  3138.     else
  3139.         m_fWeaponYVel += dz * kWeapStiffnessB;
  3140.     m_fWeaponY += m_fWeaponYVel;
  3141. }
  3142.  
  3143.  
  3144.  
  3145. // ----------------------------------------------------------------------- //
  3146. //
  3147. //    ROUTINE:    CBloodClientShell::UpdateHeadCant()
  3148. //
  3149. //    PURPOSE:    Update head tilt when strafing
  3150. //
  3151. // ----------------------------------------------------------------------- //
  3152.  
  3153. void CBloodClientShell::UpdateHeadCant()
  3154. {
  3155.     CClientDE* pClientDE = GetClientDE();
  3156.  
  3157.     // If we are strafing, cant our head as we move..
  3158.  
  3159.         // Strafe.. Check for strafe modifier first
  3160.     if ((pClientDE->IsCommandOn(COMMAND_STRAFE) && pClientDE->IsCommandOn(COMMAND_LEFT)) ||
  3161.         pClientDE->IsCommandOn(COMMAND_STRAFELEFT))
  3162.     {
  3163.         m_fCamCant -= m_fCantIncrement;
  3164.         if(m_fCamCant < -m_fCantMaxDist)
  3165.             m_fCamCant = -m_fCantMaxDist;
  3166.     }
  3167.     else if ((pClientDE->IsCommandOn(COMMAND_STRAFE) && pClientDE->IsCommandOn(COMMAND_RIGHT)) ||
  3168.         pClientDE->IsCommandOn(COMMAND_STRAFERIGHT))
  3169.     {
  3170.         m_fCamCant += m_fCantIncrement;
  3171.         if(m_fCamCant > m_fCantMaxDist)
  3172.             m_fCamCant = m_fCantMaxDist;
  3173.     }
  3174.     else 
  3175.     {
  3176.         // We are not canting so move us toward zero...
  3177.         if(m_fCamCant != 0.0f)
  3178.         {
  3179.             if(m_fCamCant < 0.0f) 
  3180.             {
  3181.                 m_fCamCant += m_fCantIncrement;
  3182.             } 
  3183.             else 
  3184.             {
  3185.                 m_fCamCant -= m_fCantIncrement;
  3186.             }
  3187.             if(fabs(m_fCamCant) < m_fCantIncrement)
  3188.                 m_fCamCant = 0.0f;
  3189.          }
  3190.     }
  3191. }
  3192.  
  3193.  
  3194. // ----------------------------------------------------------------------- //
  3195. //
  3196. //    ROUTINE:    CBloodClientShell::UpdatePlayerCamera()
  3197. //
  3198. //    PURPOSE:    Update the player camera
  3199. //
  3200. // ----------------------------------------------------------------------- //
  3201.  
  3202. DBOOL CBloodClientShell::UpdatePlayerCamera()
  3203. {
  3204.     CClientDE* pClientDE = GetClientDE();
  3205.     if (!pClientDE || !m_hCamera || !m_pMoveMgr) return DFALSE;
  3206.  
  3207.     // Make sure our player camera is attached...
  3208.  
  3209.     m_playerCamera.AttachToObject(m_pMoveMgr->GetObject());
  3210.  
  3211.     // Update our camera position based on the player camera...
  3212.  
  3213.     m_playerCamera.CameraUpdate(pClientDE->GetFrameTime());
  3214.  
  3215.     return DTRUE;
  3216. }
  3217.  
  3218.  
  3219. void CBloodClientShell::GetCameraRotation(DRotation *pRot)
  3220. {
  3221.     GetClientDE()->SetupEuler(pRot, m_fPitch, m_fYaw, m_fCamCant);
  3222. }
  3223.  
  3224.  
  3225.  
  3226. // --------------------------------------------------------------------------- //
  3227. //
  3228. //    ROUTINE:    CBloodClientShell::SetCameraStuff
  3229. //
  3230. //    PURPOSE:    Sets the camera field of view, rect & zoom mode.
  3231. //
  3232. // --------------------------------------------------------------------------- //
  3233. void CBloodClientShell::SetCameraStuff(HLOCALOBJ hPlayerObj, HLOCALOBJ hCamera)
  3234. {
  3235.     float oldFovX;
  3236.     float zoomSpeed;
  3237.  
  3238.     float fFOVx, fFOVy;
  3239.     int nLeft, nTop, nBottom, nRight;
  3240.  
  3241.     CClientDE* pClientDE = GetClientDE();
  3242.  
  3243.     pClientDE->GetSurfaceDims (pClientDE->GetScreenSurface(), &m_dwScreenWidth, &m_dwScreenHeight);
  3244.  
  3245.     cdata.byFlags |= CDATA_CANMOVE;
  3246.  
  3247.     if (m_hSeeingEyeObj)
  3248.     {
  3249.         nLeft = 0;
  3250.         nTop = 0;
  3251.         nRight = m_dwScreenWidth - 1;
  3252.         nBottom = m_dwScreenHeight - 1;
  3253.  
  3254.         fFOVx = DEG2RAD(m_DefFovX + 45);
  3255.         fFOVy = fFOVx * m_fovYScale;
  3256.  
  3257.         cdata.byFlags &= ~CDATA_CANMOVE;
  3258.     }
  3259.     else if (m_hOrbObj)
  3260.     {
  3261.         nLeft = 0;
  3262.         nTop = 0;
  3263.         nRight = m_dwScreenWidth - 1;
  3264.         nBottom = m_dwScreenHeight - 1;
  3265.  
  3266.         fFOVx = DEG2RAD(m_DefFovX + 45);
  3267.         fFOVy = fFOVx * m_fovYScale;
  3268.  
  3269.         cdata.byFlags &= ~CDATA_CANMOVE;
  3270.     }
  3271.     else if (m_pExternalCamera)
  3272.     {
  3273.         if (m_pExternalCamera->GetType() == CAMTYPE_LETTERBOX)
  3274.         {
  3275.             nLeft = 0;
  3276.             nTop = m_dwScreenHeight / 6;
  3277.             nRight = m_dwScreenWidth - 1;
  3278.             nBottom = m_dwScreenHeight - nTop - 1;
  3279.  
  3280.             fFOVx = DEG2RAD(m_DefFovX);
  3281.             fFOVy = fFOVx * 0.55f;
  3282.         }
  3283.         else
  3284.         {
  3285.             m_fovY = m_fovX * m_fovYScale;
  3286.  
  3287.             nLeft = 0;
  3288.             nTop = 0;
  3289.             nRight = m_dwScreenWidth - 1;
  3290.             nBottom = m_dwScreenHeight - 1;
  3291.  
  3292.             fFOVx = m_fovX;
  3293.             fFOVy = m_fovY;
  3294.         }
  3295.         if (!m_pExternalCamera->GetPlayerMovement())
  3296.             cdata.byFlags &= ~CDATA_CANMOVE;
  3297.     }
  3298.     else
  3299.     {
  3300.         zoomSpeed = 8 * pClientDE->GetFrameTime();
  3301.  
  3302.     //    pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &Width, &Height);
  3303.     //    pClientDE->GetCameraFOV(m_hCamera, &fovX, &fovY);
  3304.  
  3305.         oldFovX = m_fovX;
  3306.  
  3307.         if (!m_fovX)
  3308.         {
  3309.             m_fovX = DEG2RAD(m_DefFovX);
  3310.         }
  3311.  
  3312.         // Need to zoom camera
  3313.         if (m_bZoomView && m_fovX > DEG2RAD(FOV_ZOOMED))
  3314.         {
  3315.             m_fovX -= zoomSpeed;
  3316.             if (m_fovX < DEG2RAD(FOV_ZOOMED)) 
  3317.             {
  3318.                 m_fovX = DEG2RAD(FOV_ZOOMED);
  3319.             }
  3320.  
  3321.             m_fovY = m_fovX * m_fovYScale;
  3322.         }
  3323.         else if (!m_bZoomView && m_fovX < DEG2RAD(m_DefFovX))
  3324.         {
  3325.             m_fovX += zoomSpeed;
  3326.  
  3327.             if (m_fovX > DEG2RAD(m_DefFovX))
  3328.                 m_fovX = DEG2RAD(m_DefFovX);
  3329.  
  3330.             m_fovY = m_fovX * m_fovYScale;
  3331.         }
  3332.         else if (!m_bZoomView && m_fovX > DEG2RAD(m_DefFovX))
  3333.         {
  3334.             m_fovX -= zoomSpeed;
  3335.  
  3336.             if (m_fovX < DEG2RAD(m_DefFovX))
  3337.                 m_fovX = DEG2RAD(m_DefFovX);
  3338.  
  3339.             m_fovY = m_fovX * m_fovYScale;
  3340.         }
  3341.  
  3342.         nLeft = 0;
  3343.         nTop = 0;
  3344.         nRight = m_dwScreenWidth - 1;
  3345.         nBottom = m_dwScreenHeight - 1;
  3346.  
  3347.         fFOVx = m_fovX;
  3348.         fFOVy = m_fovY;
  3349.     }
  3350.  
  3351.     pClientDE->SetCameraRect(m_hCamera, DFALSE, nLeft, nTop, nRight, nBottom);
  3352.     pClientDE->SetCameraFOV(m_hCamera, fFOVx, fFOVy);
  3353. }
  3354.  
  3355.  
  3356.  
  3357.     
  3358. // --------------------------------------------------------------------------- //
  3359. //
  3360. //    ROUTINE:    CBloodClientShell::OnCommandOn()
  3361. //
  3362. //    PURPOSE:    Called upon command activation.
  3363. //
  3364. // --------------------------------------------------------------------------- //
  3365. void CBloodClientShell::OnCommandOn(int command)
  3366. {
  3367.     CClientDE* pClientDE = GetClientDE();
  3368.     if (!pClientDE) return;
  3369.  
  3370.     switch(command)
  3371.     {
  3372.         // Auto Run
  3373.         case COMMAND_RUNLOCK:
  3374.             if (!m_MessageMgr.GetEditingState())
  3375.             {
  3376.                 HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_AUTORUN);
  3377.                 if(szErrorStr)
  3378.                 {
  3379.                     _mbscpy((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr));
  3380.                     pClientDE->FreeString(szErrorStr);
  3381.                 }
  3382.  
  3383.                 // Toggle runlock flag
  3384.                 if (cdata.byFlags & CDATA_RUNLOCK)
  3385.                 {
  3386.                     cdata.byFlags &= ~CDATA_RUNLOCK;
  3387.  
  3388.                     szErrorStr = pClientDE->FormatString(IDS_GENERAL_OFF);
  3389.                     if(szErrorStr)
  3390.                     {
  3391.                         _mbscat((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr));
  3392.                         pClientDE->FreeString(szErrorStr);
  3393.                     }
  3394.  
  3395.                     pClientDE->RunConsoleString("+RunLock 0");
  3396.                 }
  3397.                 else
  3398.                 {
  3399.                     cdata.byFlags |= CDATA_RUNLOCK;
  3400.  
  3401.                     szErrorStr = pClientDE->FormatString(IDS_GENERAL_ON);
  3402.                     if(szErrorStr)
  3403.                     {
  3404.                         _mbscat((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr));
  3405.                         pClientDE->FreeString(szErrorStr);
  3406.                     }
  3407.  
  3408.                     pClientDE->RunConsoleString("+RunLock 1");
  3409.                 }
  3410.  
  3411.                 CSPrint(msgbuf);
  3412.             }
  3413.             break;
  3414.  
  3415.         // Mouse aiming toggle
  3416. /*        case COMMAND_MOUSEAIMTOGGLE:
  3417.             if (!m_MessageMgr.GetEditingState())
  3418.             {
  3419.                 _mbscpy(msgbuf, "MOUSE AIMING ");
  3420.                 if (cdata.byFlags & CDATA_MOUSEAIMING)
  3421.                 {
  3422.                     cdata.byFlags &= ~CDATA_MOUSEAIMING;
  3423.                     _mbscat((unsigned char*)msgbuf, (const unsigned char*)"OFF");
  3424.                     m_bZeroXAngle = DTRUE;
  3425.  
  3426.                     pClientDE->RunConsoleString("+MouseLook 0");
  3427.                 }
  3428.                 else
  3429.                 {
  3430.                     cdata.byFlags |= CDATA_MOUSEAIMING;
  3431.                     _mbscat((unsigned char*)msgbuf, (const unsigned char*)"ON");
  3432.  
  3433.                     pClientDE->RunConsoleString("+MouseLook 1");
  3434.                 }
  3435.  
  3436.                 CSPrint(msgbuf);
  3437.             }
  3438.             break;
  3439. */
  3440.         case COMMAND_LOOKUP: 
  3441.             if (!m_MessageMgr.GetEditingState())
  3442.             {
  3443.                 m_bZeroXAngle = DFALSE;
  3444.             }    
  3445.             break;
  3446.  
  3447.         case COMMAND_LOOKDOWN: 
  3448.             if (!m_MessageMgr.GetEditingState())
  3449.             {
  3450.                 m_bZeroXAngle = DFALSE;
  3451.             }
  3452.             break;
  3453.  
  3454.         case COMMAND_CROSSHAIR:
  3455.             if (!m_MessageMgr.GetEditingState() && !m_bZoomView)
  3456.             {
  3457.                 if(m_bShiftState == DTRUE)
  3458.                 {
  3459.                     m_nCrosshair++;
  3460.                     if(m_nCrosshair > 41)    m_nCrosshair = 0;
  3461.                     m_nCrosshairOriginalNum = m_nCrosshair;
  3462.  
  3463.                     char str[64];
  3464.                     sprintf(str, "+CrosshairNum %d", m_nCrosshair);
  3465.                     pClientDE->RunConsoleString(str);
  3466.                 }
  3467.                 else
  3468.                 {
  3469.                     m_bShowCrosshair = !m_bShowCrosshair;
  3470.                     m_bCrosshairOriginallyOn = m_bShowCrosshair;
  3471.  
  3472.                     if(m_bShowCrosshair)
  3473.                         pClientDE->RunConsoleString("+Crosshair 1");
  3474.                     else
  3475.                         pClientDE->RunConsoleString("+Crosshair 0");
  3476.                 }
  3477.             }
  3478.             break;
  3479.  
  3480.         case COMMAND_SCREENSHRINK:
  3481.             //m_NewStatusBar.StatLevelUp();
  3482.             break;
  3483.  
  3484.         case COMMAND_SCREENENLARGE:
  3485.             //m_NewStatusBar.StatLevelDown();
  3486.             break;
  3487.  
  3488.         case COMMAND_USE:
  3489.             if(m_bDead && GetGameState() == GS_PLAYING)
  3490.             {
  3491.                 if(IsMultiplayerGame())
  3492.                 {
  3493.                     m_pMoveMgr->ClearControlFlags();
  3494.  
  3495.                     if (m_pWeapon)        m_pWeapon->CancelFiringState();
  3496.                     if (m_pLWeapon)        m_pLWeapon->CancelFiringState();
  3497.  
  3498.                     if (m_pWeapon) 
  3499.                     {
  3500.                         delete m_pWeapon;
  3501.                         m_pWeapon = DNULL;
  3502.                     }
  3503.                     if (m_pLWeapon) 
  3504.                     {
  3505.                         delete m_pLWeapon;
  3506.                         m_pLWeapon = DNULL;
  3507.                     }
  3508.  
  3509.                     if (m_abyWeaponID[m_nCurGun])
  3510.                         m_pWeapon = CreateWeapon(m_abyWeaponID[m_nCurGun], DFALSE);
  3511.                     if (m_abyLWeaponID[m_nCurGun])
  3512.                         m_pLWeapon = CreateWeapon(m_abyLWeaponID[m_nCurGun], DTRUE);
  3513.                 }
  3514.                 else
  3515.                 {
  3516.                     pClientDE->RunConsoleString("NumConsoleLines 0");
  3517.  
  3518.                     SetGameState(GS_MENU);
  3519.                     PauseGame(DTRUE);
  3520.                     SetGameState(GS_MENU);
  3521.  
  3522. #ifdef _DEMO
  3523.                     m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  3524. #else
  3525.                     m_Menu.SetCurrentMenu(MENU_ID_LOAD_GAME, MENU_ID_LOAD_GAME);
  3526. #endif
  3527.                 }
  3528.             }
  3529.             break;
  3530.     }
  3531. }
  3532.  
  3533.  
  3534. // --------------------------------------------------------------------------- //
  3535. //
  3536. //    ROUTINE:    CBloodClientShell::OnCommandOff()
  3537. //
  3538. //    PURPOSE:    Called upon command deactivation.
  3539. //
  3540. // --------------------------------------------------------------------------- //
  3541. void CBloodClientShell::OnCommandOff(int command)
  3542. {
  3543.     CClientDE* pClientDE = GetClientDE();
  3544.     if (!pClientDE) return;
  3545.  
  3546.     if (!m_MessageMgr.GetEditingState())
  3547.     {
  3548.         switch(command)
  3549.         {
  3550.             // Mouse aiming toggle
  3551.             case COMMAND_MOUSEAIMTOGGLE:
  3552.             {
  3553.                 if (!m_MessageMgr.GetEditingState() && m_bLookSpring && !m_bMouseLook)
  3554.                     m_bZeroXAngle = DTRUE;
  3555.             }
  3556.             break;
  3557.  
  3558.             case COMMAND_LOOKUP: 
  3559.             case COMMAND_LOOKDOWN: 
  3560.             {
  3561.                 if (m_bLookSpring)
  3562.                     m_bZeroXAngle = DTRUE;        
  3563.             }
  3564.             break;
  3565.             
  3566.             case COMMAND_USE:
  3567.             {
  3568.                 if(m_pCreature)
  3569.                     m_pCreature->UseKeyHit();
  3570.             }
  3571.             break;
  3572.  
  3573.             case COMMAND_MESSAGE:
  3574.             {
  3575.                 if(GetGameState() == GS_PLAYING)
  3576.                 {
  3577.                     m_MessageMgr.SetEditingState(DTRUE);
  3578.                     pClientDE->SetInputState(DFALSE);
  3579.                 }
  3580.             }
  3581.             break;
  3582.  
  3583.             default: return;
  3584.         }
  3585.     }
  3586. }
  3587.  
  3588.  
  3589. // --------------------------------------------------------------------------- //
  3590. //
  3591. //    ROUTINE:    CBloodClientShell::OnKeyDown()
  3592. //
  3593. //    PURPOSE:    Called upon a key down message from Windows.
  3594. //
  3595. // --------------------------------------------------------------------------- //
  3596. void CBloodClientShell::OnKeyDown(int key, int rep)
  3597. {
  3598.     CClientDE* pClientDE = GetClientDE();
  3599.     if (!pClientDE) return;
  3600.  
  3601.     // This is used to ignore a keyboard message which is used while
  3602.     // configuring the keys on the keyboard.
  3603.     if (m_bIgnoreKeyboardMessage)
  3604.     {
  3605.         m_bIgnoreKeyboardMessage=DFALSE;
  3606.         return;
  3607.     }
  3608.  
  3609.     // Track shift keys.
  3610.     if (key == VK_SHIFT || key == VK_LSHIFT || key == VK_RSHIFT)
  3611.         m_bShiftState = DTRUE;
  3612.  
  3613.     // The message box will receive all keyboard input if it is up
  3614.     if (m_bInMessageBox)
  3615.     {
  3616.         m_messageBox.HandleKeyDown(key, rep);
  3617.         return;
  3618.     }
  3619.  
  3620.     if (m_bRollCredits && GetGameState() != GS_CREDITS)
  3621.     {
  3622.         m_Credits.HandleInput(key);
  3623.     }
  3624.  
  3625.     if (m_MessageMgr.GetEditingState())
  3626.     {
  3627.         m_MessageMgr.HandleKeyDown(key, rep);
  3628.     }
  3629.     else if (GetGameState() == GS_SPLASH)
  3630.     {
  3631.         Splash_OnKeyDown(key);
  3632.         return;
  3633.     }
  3634.     else if (GetGameState() == GS_MOVIES)
  3635.     {
  3636.         if (key == VK_ESCAPE)
  3637.         {
  3638.             AdvanceMovies(pClientDE);
  3639.         }
  3640.         return;
  3641.     }
  3642.     else if (GetGameState() == GS_CREDITS)
  3643.     {
  3644.         if (key == VK_ESCAPE)
  3645.         {
  3646.             m_Credits.Term();
  3647.  
  3648.             if (m_bInWorld)
  3649.             {
  3650.                 SetGameState(GS_PLAYING);
  3651.                 PauseGame(DFALSE);
  3652.             }
  3653.             else
  3654.             {
  3655.                 SetGameState(GS_MENU);
  3656.                 m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  3657.             }
  3658.         }
  3659.         else
  3660.         {
  3661.             m_Credits.HandleInput (key);
  3662.         }
  3663.     }
  3664.     else if (GetGameState() == GS_WAITING)
  3665.     {
  3666.         SetGameState(GS_PLAYING);
  3667.         PauseGame(DFALSE);
  3668.     }
  3669.     else if (GetGameState() == GS_MENU)
  3670.     {
  3671.         // Process the keyboard commands in the menu class
  3672.         m_Menu.HandleKeyDown(key, rep);
  3673.     }
  3674.     else if (key == VK_ESCAPE)
  3675.     {
  3676.         if (GetGameState() == GS_MENU && m_bInWorld)
  3677.         {
  3678.             SetGameState(GS_PLAYING);
  3679.             PauseGame(DFALSE);
  3680.  
  3681.             if (g_bLevelChange3rdPersonCam)
  3682.             {
  3683.                 pClientDE->SetInputState(DFALSE);
  3684.                 if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE);
  3685.                 m_bDrawFragBar = DTRUE;
  3686.             }
  3687.         }
  3688.         else if (GetGameState() == GS_PLAYING)
  3689.         {
  3690.             pClientDE->RunConsoleString("NumConsoleLines 0");
  3691.             
  3692.             SetGameState(GS_MENU);
  3693.             PauseGame(DTRUE);
  3694.             m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  3695.         }
  3696.     }
  3697.     else if ((key == VK_F1) && !m_bShiftState)
  3698.     {
  3699.         m_NewStatusBar.ToggleWeapons();
  3700.     }
  3701.     else if (key == VK_TAB)
  3702.     {
  3703.         if(IsMultiplayerGame())
  3704.         {
  3705.             m_bDrawFragBar = !m_bDrawFragBar;
  3706.             if (m_bDrawFragBar) m_FragInfo.TurnOn();
  3707.             else m_FragInfo.TurnOff();
  3708.         }
  3709.         else
  3710.         {
  3711.             if (GetGameType() == GAMETYPE_SINGLE || GetGameType() == GAMETYPE_CUSTOM)
  3712.             {
  3713.                 m_NewStatusBar.ToggleObjectives();
  3714.             }
  3715.         }
  3716.     }
  3717.     else if (m_bShiftState)        // Special functions for these keys..
  3718.     {
  3719.         if (key >= VK_F1 && key <= VK_F12)    // Text macros..
  3720.         {
  3721.             int n = key - VK_F1 + 1;
  3722.             sprintf(msgbuf, "macro%d", n);
  3723.             HCONSOLEVAR hVar;
  3724.             if (hVar = pClientDE->GetConsoleVar (msgbuf))
  3725.             {
  3726.                 char* sVar = pClientDE->GetVarValueString(hVar);
  3727.                 if (sVar && sVar[0] != '\0')
  3728.                 {
  3729.                     // Send the macro...
  3730.                     HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_PLAYERMESSAGE);
  3731.                     pClientDE->WriteToMessageString(hMsg, sVar);
  3732.                     pClientDE->EndMessage(hMsg);
  3733.                 }
  3734.             }
  3735.         }
  3736. /*        else if (key == VK_ADD || key == 0x00BB)
  3737.         {
  3738.             m_fovYScale += .01f;
  3739.  
  3740.             HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, m_fovYScale);
  3741.             CSPrint(pClientDE->GetStringData(szErrorStr));
  3742.             pClientDE->FreeString(szErrorStr);
  3743. //            CSPrint("FOV Y Scale: %.2f", m_fovYScale);
  3744.         }
  3745.         else if (key == VK_SUBTRACT || key == 0x00BD)
  3746.         {
  3747.             m_fovYScale -= .01f;
  3748.  
  3749.             HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, m_fovYScale);
  3750.             CSPrint(pClientDE->GetStringData(szErrorStr));
  3751.             pClientDE->FreeString(szErrorStr);
  3752. //            CSPrint("FOV Y Scale: %.2f", m_fovYScale);
  3753.         }
  3754.         else if (key == 0x00DB)
  3755.         {
  3756.             m_DefFovX -= 0.25f;
  3757.  
  3758.             HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVX, m_DefFovX);
  3759.             CSPrint(pClientDE->GetStringData(szErrorStr));
  3760.             pClientDE->FreeString(szErrorStr);
  3761. //            CSPrint("FOV X: %.2f deg.", m_DefFovX);
  3762.         }
  3763.         else if (key == 0x00DD)
  3764.         {
  3765.             m_DefFovX += 0.25f;
  3766.  
  3767.             HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVX, m_DefFovX);
  3768.             CSPrint(pClientDE->GetStringData(szErrorStr));
  3769.             pClientDE->FreeString(szErrorStr);
  3770. //            CSPrint("FOV X: %.2f deg.", m_DefFovX);
  3771.         }*/
  3772.  
  3773. #ifdef _DEBUG
  3774.         // 09/12/97 
  3775.         // Add option to move weapon in the game... viewing of the weapon
  3776.         // Move Weapon X,Y,Z
  3777.         if (m_pWeapon)
  3778.         {
  3779.             DVector offset = m_pWeapon->GetGunOffset();
  3780.  
  3781.             if (key == 'B')
  3782.             {
  3783.                 offset.x += 0.1f;
  3784.  
  3785.                 HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, offset.x);
  3786. //                CSPrint(szErrorStr);
  3787.                 pClientDE->FreeString(szErrorStr);
  3788.  
  3789.                 sprintf(msgbuf, "Gun: m_GunOffset.x %.1f", offset.x);
  3790.                 CSPrint(msgbuf);
  3791.             }
  3792.  
  3793.             // Move Weapon X,Y,Z
  3794.             if (key == 'N')
  3795.             {
  3796.                 offset.y += 0.1f;
  3797.                 sprintf(msgbuf, "Gun: m_GunOffset.y %.1f", offset.y);
  3798.                 CSPrint(msgbuf);
  3799.             }
  3800.  
  3801.             // Move Weapon X,Y,Z
  3802.             if (key == 'M')
  3803.             {
  3804.                 offset.z += 0.1f;
  3805.                 sprintf(msgbuf, "Gun: m_GunOffset.z %.1f", offset.z);
  3806.                 CSPrint(msgbuf);
  3807.             }
  3808.  
  3809.             // Move Weapon X,Y,Z
  3810.             if (key == 'H')
  3811.             {
  3812.                 offset.x -= 0.1f;
  3813.                 sprintf(msgbuf, "Gun: m_GunOffset.x %.1f", offset.x);
  3814.                 CSPrint(msgbuf);
  3815.             }
  3816.  
  3817.             // Move Weapon X,Y,Z
  3818.             if (key == 'J')
  3819.             {
  3820.                 offset.y -= 0.1f;
  3821.                 sprintf(msgbuf, "Gun: m_GunOffset.y %.1f", offset.y);
  3822.                 CSPrint(msgbuf);
  3823.             }
  3824.  
  3825.             // Move Weapon X,Y,Z
  3826.             if (key == 'K')
  3827.             {
  3828.                 offset.z -= 0.1f;
  3829.                 sprintf(msgbuf, "Gun: m_GunOffset.z %.1f", offset.z);
  3830.                 CSPrint(msgbuf);
  3831.             }
  3832.  
  3833.             if (m_pWeapon)
  3834.             {
  3835.                 m_pWeapon->SetGunOffset(offset);
  3836.             }
  3837.  
  3838.             if (m_pLWeapon)
  3839.             {
  3840.                 offset.x = -offset.x;
  3841.                 m_pLWeapon->SetGunOffset(offset);
  3842.             }
  3843.         }
  3844. #endif
  3845.     }
  3846.     else if(key == VK_F2)        // Save Game
  3847.     {
  3848.         if (GetGameState() == GS_PLAYING)
  3849.         {
  3850. #ifndef _DEMO
  3851.             PauseGame(DTRUE);
  3852.             SetGameState(GS_MENU);
  3853.             m_Menu.SetCurrentMenu(MENU_ID_SAVE_GAME, MENU_ID_SAVE_GAME);
  3854. #endif
  3855.         }
  3856.     }
  3857.     else if(key == VK_F3)        // Load Game
  3858.     {
  3859.         if (GetGameState() == GS_PLAYING)
  3860.         {
  3861. #ifndef _DEMO
  3862.             PauseGame(DTRUE);
  3863.             SetGameState(GS_MENU);
  3864.             m_Menu.SetCurrentMenu(MENU_ID_LOAD_GAME, MENU_ID_LOAD_GAME);
  3865. #endif
  3866.         }
  3867.     }
  3868.     else if(key == VK_F4)        // Options
  3869.     {
  3870.         if (GetGameState() == GS_PLAYING)
  3871.         {
  3872.             PauseGame(DTRUE);
  3873.             SetGameState(GS_MENU);
  3874.             m_Menu.SetCurrentMenu(MENU_ID_OPTIONS, MENU_ID_OPTIONS);
  3875.         }
  3876.     }
  3877.     else if(key == VK_F5)        // Quicksave
  3878.     {
  3879.         if (GetGameState() == GS_PLAYING && m_bInWorld && !m_bDead && !IsMultiplayerGame())
  3880.         {
  3881. #ifndef _DEMO
  3882.             MenuSaveGame(SLOT_QUICK);
  3883.             DoMessageBox("Quicksave...", DFALSE);
  3884. #endif
  3885.         }
  3886.     }
  3887.     else if (key == VK_F6)        // Quickload
  3888.     {
  3889.         if (GetGameState() == GS_PLAYING && !IsMultiplayerGame())
  3890.         {
  3891. #ifndef _DEMO
  3892.             if (MenuLoadGame(SLOT_QUICK))
  3893.             DoMessageBox("Quickload...", DFALSE);
  3894. #endif
  3895.         }
  3896.     }
  3897. }
  3898.  
  3899.  
  3900.  
  3901.  
  3902. // --------------------------------------------------------------------------- //
  3903. //
  3904. //    ROUTINE:    CBloodClientShell::StartNewGame()
  3905. //
  3906. //    PURPOSE:    Starts a new game
  3907. //
  3908. // --------------------------------------------------------------------------- //
  3909.  
  3910. DBOOL CBloodClientShell::StartNewGame(char *pszWorldName, DBYTE nStartType, DBYTE nGameType, DBYTE nLoadType, DBYTE nDifficulty)
  3911. {
  3912.     CClientDE* pClientDE = GetClientDE();
  3913.     HCONSOLEVAR hVar;
  3914.  
  3915.     // Initialize some stuff
  3916.     m_nCurGun        = 0;
  3917.  
  3918.     m_bSpectatorMode = DFALSE;
  3919.  
  3920.     m_fEyeLevel        = 0;
  3921.     m_bZoomView        = DFALSE;
  3922.     m_hSeeingEyeObj = DNULL;
  3923.     m_hOrbObj        = DNULL;
  3924.     m_hLastOrbObj    = DNULL;
  3925.  
  3926.     if( m_hNightGogglesSound )
  3927.     {
  3928.         g_pClientDE->KillSound( m_hNightGogglesSound );
  3929.         m_hNightGogglesSound = DNULL;
  3930.     }
  3931.  
  3932.     if( m_hTheEyeLoopingSound )
  3933.     {
  3934.         g_pClientDE->KillSound( m_hTheEyeLoopingSound );
  3935.         m_hTheEyeLoopingSound = DNULL;
  3936.     }
  3937.  
  3938.     m_bNightGogglesActive = DFALSE;
  3939.  
  3940.     m_bBinocularsActive = DFALSE;
  3941.  
  3942.     hVar = pClientDE->GetConsoleVar ("CrosshairNum");
  3943.     m_nCrosshair = (DBYTE)pClientDE->GetVarValueFloat(hVar);
  3944.     if(m_nCrosshair > 41) m_nCrosshair = 0;
  3945.     m_nCrosshairOriginalNum = m_nCrosshair;
  3946.  
  3947.     m_playerCamera.SetFirstPerson();
  3948.     m_b3rdPerson    = DFALSE;
  3949.  
  3950.     memset(&m_Request, 0, sizeof(StartGameRequest));
  3951.     m_Request.m_Type = nStartType;
  3952.     pClientDE->StartGame(&m_Request);
  3953.  
  3954.     // Reset the voice manager...
  3955.     GetVoiceMgr()->Reset();
  3956.  
  3957.     m_eMusicLevel = CMusic::MUSICLEVEL_SILENCE;
  3958.  
  3959.     // Send a message to the server to restore the autosave
  3960.     if (pszWorldName)
  3961.         _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)pszWorldName);
  3962.  
  3963.     return StartNewWorld(m_szFilename, nGameType, nLoadType, nDifficulty);
  3964. }
  3965.  
  3966.  
  3967. // --------------------------------------------------------------------------- //
  3968. //
  3969. //    ROUTINE:    CBloodClientShell::OnKeyUp()
  3970. //
  3971. //    PURPOSE:    Called upon a key up message from Windows.
  3972. //
  3973. // --------------------------------------------------------------------------- //
  3974. void CBloodClientShell::OnKeyUp(int key)
  3975. {
  3976.     // Track shift keys.
  3977.     if (key == VK_SHIFT || key == VK_LSHIFT || key == VK_RSHIFT)
  3978.         m_bShiftState = DFALSE;
  3979.  
  3980.     m_MessageMgr.HandleKeyUp(key);
  3981.  
  3982.     if (GetGameState() == GS_MENU)
  3983.     {
  3984.         m_Menu.HandleKeyUp(key);
  3985.     }
  3986. }
  3987.  
  3988.  
  3989. // --------------------------------------------------------------------------- //
  3990. //
  3991. //    ROUTINE:    CBloodClientShell::OnMessage()
  3992. //
  3993. //    PURPOSE:    Called when a message is received from the server.
  3994. //
  3995. // --------------------------------------------------------------------------- //
  3996. void CBloodClientShell::OnMessage(DBYTE messageID, HMESSAGEREAD hMessage)
  3997. {
  3998.     DBYTE tbyte;
  3999.  
  4000.     CClientDE* pClientDE = GetClientDE();
  4001.  
  4002.     switch(messageID)
  4003.     {
  4004.         case SMSG_BOOTED:
  4005.         {
  4006.             CSPrint(IDS_BOOTED);
  4007.             PlaySound(MSG_SOUND_STRING);
  4008.             break;
  4009.         }
  4010.  
  4011.         case SMSG_SERVERSHUTDOWN:
  4012.         {
  4013.             CSPrint(IDS_SERVERSHUTDOWN);
  4014.             PlaySound(MSG_SOUND_STRING);
  4015.             break;
  4016.         }
  4017.  
  4018.         case SMSG_PINGTIMES:
  4019.         {
  4020.             while(1)
  4021.             {
  4022.                 D_WORD id, ping;
  4023.  
  4024.                 id = pClientDE->ReadFromMessageWord(hMessage);
  4025.                 if(id == 0xFFFF) break;
  4026.  
  4027.                 ping = pClientDE->ReadFromMessageWord(hMessage);
  4028.  
  4029.                 m_FragInfo.UpdatePlayerPing(id, ping);
  4030.             }
  4031.         }
  4032.         break;
  4033.  
  4034.         case SMSG_PHYSICS_UPDATE:
  4035.         {
  4036.             if(m_pMoveMgr)
  4037.                 m_pMoveMgr->OnPhysicsUpdate(hMessage);
  4038.         }
  4039.         break;
  4040.  
  4041.         case SMSG_FORCEPOS:
  4042.         {
  4043.             if(m_pMoveMgr)
  4044.                 m_pMoveMgr->OnServerForcePos(hMessage);
  4045.         }
  4046.         break;
  4047.  
  4048.         case SMSG_PLAYERSTATSUPDATE:
  4049.             {
  4050.                 DBYTE nStatsFlags = pClientDE->ReadFromMessageByte(hMessage);
  4051.                 if( nStatsFlags & PLAYERSTATS_HEALTH )
  4052.                 {
  4053.                     DDWORD nHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4054.                     DDWORD nMaxHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4055.                     m_NewStatusBar.SetHealth(nHealth, nMaxHealth);
  4056.                     m_nHealth = nHealth;
  4057.  
  4058.                     if (m_bDead && m_nHealth >= 0)
  4059.                     {
  4060.                         m_playerCamera.SetFirstPerson();
  4061.                         m_bDead        = DFALSE;
  4062.                         m_bDeadNoHide  = DFALSE;
  4063.                         m_bDrawFragBar = DFALSE;
  4064.                         m_bBlind       = DFALSE;
  4065.                         m_nTrapped     = 0;
  4066.  
  4067.                         // Turn off wonkyvision if it was on.
  4068.                         EndWonkyVision();
  4069.                     }
  4070.                 }
  4071.                 if( nStatsFlags & PLAYERSTATS_AMMO )
  4072.                 {
  4073.                     DDWORD dwAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4074.                     m_NewStatusBar.SetAmmo(dwAmmo);
  4075.                     m_dwAmmo = dwAmmo;
  4076.                 }
  4077.                 if( nStatsFlags & PLAYERSTATS_ALTAMMO )
  4078.                 {
  4079.                     DDWORD dwAltAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4080.                     m_dwAltAmmo = dwAltAmmo;
  4081.  
  4082.                     if(m_pWeapon && (m_pWeapon->GetAmmoType(DTRUE) != m_pWeapon->GetAmmoType(DFALSE)))
  4083.                         m_NewStatusBar.SetAltAmmo(dwAltAmmo);
  4084.                     else
  4085.                         m_NewStatusBar.SetAltAmmo(0);
  4086.                 }
  4087.                 if( nStatsFlags & PLAYERSTATS_ARMOR )
  4088.                 {
  4089.                     DDWORD nArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4090.                     DDWORD nMaxArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4091.                     m_NewStatusBar.SetArmor(nArmor, nMaxArmor);
  4092.                 }
  4093.                 if( nStatsFlags & PLAYERSTATS_FOCUS )
  4094.                 {
  4095.                     DDWORD nAmmo = pClientDE->ReadFromMessageWord(hMessage);
  4096.                 }
  4097.                 if( nStatsFlags & PLAYERSTATS_TOOKDAMAGE )
  4098.                 {
  4099.                     DFLOAT fDamage = (DFLOAT)pClientDE->ReadFromMessageByte(hMessage);
  4100.                     DBYTE nDamageType = pClientDE->ReadFromMessageByte(hMessage);
  4101.  
  4102.                     if (nDamageType != DAMAGE_TYPE_FREEFALL)
  4103.                     {
  4104.                         // Flash the screen up to 1 seconds depending on damage
  4105.                         DFLOAT fTime = (fDamage/200.0f);
  4106.                         // Ramp up = 0.2f
  4107.                         // Ramp down = 0.2f
  4108.                         DVector vFlashColor;
  4109.                         DFLOAT fRed = fDamage / 200.0f;
  4110.  
  4111.                         // minimum flash should be 0.2
  4112.                         if (m_vFlashColor.x < 0.2f && fRed < 0.2f) fRed = 0.2f;
  4113.                         VEC_SET(vFlashColor, fRed, 0.0f, 0.0f);
  4114.  
  4115.                         FlashScreen(&vFlashColor, fTime, 0.1f);
  4116.                     }
  4117.                 }
  4118.                 if( nStatsFlags & PLAYERSTATS_AIRLEVEL )
  4119.                 {
  4120.                     DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage);
  4121.  
  4122.                     if((fPercent <= 0.0f) || (fPercent >= 1.0f))
  4123.                         m_NewStatusBar.TurnOffPowerBar();
  4124.                     else
  4125.                         m_NewStatusBar.SetPowerBarLevel(BARTAB_AIR, fPercent);
  4126.                 }
  4127.             }
  4128.             break;
  4129.  
  4130.         case SMSG_THROWDISTANCE:
  4131.             {
  4132.                 DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage);
  4133.  
  4134.                 if((fPercent <= 0.0f) || (fPercent >= 1.0f))
  4135.                     m_NewStatusBar.TurnOffPowerBar();
  4136.                 else
  4137.                     m_NewStatusBar.SetPowerBarLevel(BARTAB_THROW, fPercent);
  4138.             }
  4139.             break;
  4140.  
  4141.         case SMSG_BOSSHEALTH:
  4142.             {
  4143.                 DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage);
  4144.  
  4145.                 if((fPercent <= 0.0f) || (fPercent >= 1.0f))
  4146.                     m_NewStatusBar.TurnOffPowerBar();
  4147.                 else
  4148.                     m_NewStatusBar.SetPowerBarLevel(BARTAB_BOSS, fPercent);
  4149.             }
  4150.             break;
  4151.  
  4152.         case SMSG_HEALTH:
  4153.             {
  4154.                 DDWORD nHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4155.                 DDWORD nMaxHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4156.                 m_NewStatusBar.SetHealth(nHealth, nMaxHealth);
  4157.                 m_nHealth = nHealth;
  4158.  
  4159.                 if (m_bDead && m_nHealth >= 0)
  4160.                 {
  4161.                     m_playerCamera.Reset();
  4162.                     m_bDead        = DFALSE;
  4163.                     m_bDrawFragBar = DFALSE;
  4164.                     m_bBlind       = DFALSE;
  4165.                     m_nTrapped     = 0;
  4166.                 }
  4167.             }
  4168.             break;
  4169.  
  4170.         case SMSG_ARMOR:
  4171.             {
  4172.                 DDWORD nArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4173.                 DDWORD nMaxArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4174.                 m_NewStatusBar.SetArmor(nArmor, nMaxArmor);
  4175.                 break;
  4176.             }
  4177.  
  4178.         case SMSG_AMMO:
  4179.             {
  4180.                 DDWORD nAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage);
  4181.                 m_NewStatusBar.SetAmmo(nAmmo);
  4182.                 break;
  4183.             }
  4184.         
  4185.         case SMSG_FOCUS:
  4186.             {
  4187.                 DDWORD nAmmo = pClientDE->ReadFromMessageWord(hMessage);
  4188.                 break;
  4189.             }
  4190.  
  4191.         case SMSG_EYELEVEL:
  4192.             m_fEyeLevel = pClientDE->ReadFromMessageFloat(hMessage);
  4193.             break;
  4194.         
  4195. #ifdef _DEBUG
  4196.         case STC_BPRINT:
  4197. #endif
  4198.         case SMSG_CONSOLEMESSAGE:
  4199.         {
  4200.             CSPrint2(pClientDE->ReadFromMessageString(hMessage));
  4201.             break;
  4202.         }
  4203.  
  4204.         case SMSG_CONSOLEMESSAGE_ALL:
  4205.         {
  4206.             CSPrint2(pClientDE->ReadFromMessageString(hMessage));
  4207.             PlaySound(MSG_SOUND_STRING);
  4208.             break;
  4209.         }
  4210.  
  4211.         case SMSG_FIREDWEAPON:
  4212.             {
  4213.                 tbyte = pClientDE->ReadFromMessageByte(hMessage);
  4214.                 if (m_pWeapon && !m_pExternalCamera)
  4215.                 {
  4216. //                    m_pWeapon->Fire(tbyte);
  4217.                     if (m_pWeapon->IsCumulativeKick())
  4218.                     {
  4219.                         m_fViewKick += m_pWeapon->GetViewKick();
  4220.                         if (m_fViewKick > 45.0f) m_fViewKick = 44.5f;
  4221.                         m_fKickTime = __max(pClientDE->GetFrameTime() * 5, 0.3f);
  4222.                     }
  4223.                     else if (m_fViewKick < m_pWeapon->GetViewKick())
  4224.                     {
  4225.                         m_fViewKick = m_pWeapon->GetViewKick();
  4226.                         m_fKickTime = 0.001f;
  4227.                     }
  4228.                 }
  4229.  
  4230.                 // Also fire the left hand weapon if we've got one
  4231.                 if (m_pLWeapon && !m_pExternalCamera)
  4232.                 {
  4233. //                    m_pLWeapon->Fire(tbyte);
  4234.                     if (m_pLWeapon->IsCumulativeKick())
  4235.                     {
  4236.                         m_fViewKick += m_pLWeapon->GetViewKick();
  4237.                         if (m_fViewKick > 45.0f) m_fViewKick = 44.5f;
  4238.                         m_fKickTime = __max(pClientDE->GetFrameTime() * 5, 0.3f);
  4239.                     }
  4240.                     else if (m_fViewKick < m_pLWeapon->GetViewKick())
  4241.                     {
  4242.                         m_fViewKick = m_pLWeapon->GetViewKick();
  4243.                         m_fKickTime = 0.001f;
  4244.                     }
  4245.                 }
  4246.             }
  4247.             break;
  4248.  
  4249.         case SMSG_TOOKDAMAGE:
  4250.             {
  4251.                 DFLOAT fDamage = (DFLOAT)pClientDE->ReadFromMessageByte(hMessage);
  4252.                 DBYTE nDamageType = pClientDE->ReadFromMessageByte(hMessage);
  4253.  
  4254.                 if (nDamageType != DAMAGE_TYPE_FREEFALL)
  4255.                 {
  4256.                     // Flash the screen up to 1 seconds depending on damage
  4257.                     DFLOAT fTime = (fDamage/200.0f);
  4258.                     // Ramp up = 0.2f
  4259.                     // Ramp down = 0.2f
  4260.                     DVector vFlashColor;
  4261.                     DFLOAT fRed = fDamage / 200.0f;
  4262.  
  4263.                     // minimum flash should be 0.2
  4264.                     if (m_vFlashColor.x < 0.2f && fRed < 0.2f) fRed = 0.2f;
  4265.                     VEC_SET(vFlashColor, fRed, 0.0f, 0.0f);
  4266.  
  4267.                     FlashScreen(&vFlashColor, fTime, 0.1f);
  4268.                 }
  4269.             }
  4270.             break;
  4271.  
  4272.  
  4273.         case SMSG_SPECTATORMODE:
  4274.             m_bSpectatorMode = pClientDE->ReadFromMessageByte(hMessage);
  4275. /*            if (m_bSpectatorMode)
  4276.             {
  4277.                 DVector vLS;
  4278.                 VEC_SET(vLS, -.5f, -.5f, -.5f);
  4279. //                pClientDE->SetGlobalLightScale(&vLS);
  4280.                 pClientDE->OffsetGlobalLightScale(&vLS);
  4281.             }
  4282.             else
  4283.             {
  4284.                 DVector vLS;
  4285.                 VEC_SET(vLS, 1.0f, 1.0f, 1.0f);
  4286. //                pClientDE->SetGlobalLightScale(&vLS);
  4287.                 pClientDE->OffsetGlobalLightScale(&vLS);
  4288.             }
  4289. */            break;
  4290.  
  4291.         case SMSG_NEWWEAPON:
  4292.             {
  4293.                 HLOCALOBJ hWeapObj = DNULL;
  4294.  
  4295.                 DBYTE bySlot          = pClientDE->ReadFromMessageByte(hMessage);
  4296.                 DBYTE byWeaponID      = pClientDE->ReadFromMessageByte(hMessage);
  4297.                 DBOOL bLeftHand          = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  4298. /*                hWeapObj              = pClientDE->ReadFromMessageObject(hMessage);
  4299.                 wd.m_szWeaponName     = pClientDE->ReadFromMessageString(hMessage);
  4300.                 wd.m_szFlashSprite    = pClientDE->ReadFromMessageString(hMessage);
  4301.                 wd.m_szAltFlashSprite = pClientDE->ReadFromMessageString(hMessage);
  4302.                 wd.m_fFlashDuration   = pClientDE->ReadFromMessageFloat(hMessage);
  4303.                 wd.m_fFlashScale      = pClientDE->ReadFromMessageFloat(hMessage);
  4304.                 pClientDE->ReadFromMessageVector(hMessage, &wd.m_GunOffset);
  4305.                 pClientDE->ReadFromMessageVector(hMessage, &wd.m_MuzzleOffset);
  4306.                 pClientDE->ReadFromMessageVector(hMessage, &wd.m_FlashPos);
  4307.                 wd.m_EjectInterval    = pClientDE->ReadFromMessageFloat(hMessage);
  4308.                 wd.m_fViewKick        = pClientDE->ReadFromMessageFloat(hMessage);
  4309.                 wd.m_bCumulativeKick  = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  4310.                 wd.m_bLeftHand          = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  4311.  
  4312.                 HSTRING weap        = pClientDE->ReadFromMessageHString(hMessage);
  4313.                 HSTRING weapH        = pClientDE->ReadFromMessageHString(hMessage);
  4314. */
  4315.                 WeaponData *wd        = &g_WeaponDefaults[byWeaponID-1];
  4316.                 HSTRING weap = DNULL, weapH = DNULL;
  4317.  
  4318.                 if(wd->m_szStatusIcon)
  4319.                     weap = pClientDE->CreateString(wd->m_szStatusIcon);
  4320.                 if(wd->m_szStatusIconH)
  4321.                     weapH = pClientDE->CreateString(wd->m_szStatusIconH);
  4322.  
  4323.                 if(bySlot < 10)
  4324.                 {
  4325.                     m_NewStatusBar.UpdateWeap(weap, weapH, bySlot);
  4326.                     m_NewStatusBar.UpdateCurrentWeap(m_nCurGun);
  4327.                 }
  4328.  
  4329.                 if (weap)        pClientDE->FreeString(weap);
  4330.                 if (weapH)        pClientDE->FreeString(weapH);
  4331.  
  4332.                 // New gun in the current slot? Get rid of what is there now..
  4333.                     // See if we already have a weapon in this slot
  4334.                 if (!bLeftHand)
  4335.                 {
  4336.                     if (m_nCurGun == bySlot)
  4337.                     {
  4338.                         if (m_pWeapon) delete m_pWeapon;
  4339.                         m_pWeapon = CreateWeapon(byWeaponID, DFALSE);
  4340.                     }
  4341.                     m_abyWeaponID[bySlot] = byWeaponID;
  4342.                 }
  4343.                 else // bLeftHand == TRUE
  4344.                 {
  4345.                     if (m_nCurGun == bySlot)
  4346.                     {
  4347.                         if (m_pLWeapon) delete m_pLWeapon;
  4348.                         m_pLWeapon = CreateWeapon(byWeaponID, DTRUE);
  4349.                     }
  4350.                     m_abyLWeaponID[bySlot] = byWeaponID;
  4351.                 }
  4352.             }
  4353.             break;
  4354.  
  4355.         case SMSG_DELETESPECIFICWEAPON:
  4356.         case SMSG_DELETEWEAPON:
  4357.         {
  4358.             DBYTE slot = pClientDE->ReadFromMessageByte(hMessage);
  4359.  
  4360.             // First see if we have a left handed model, and it's the current gun..
  4361.             if (m_abyLWeaponID[slot] && slot == m_nCurGun)
  4362.             {
  4363.                 if (m_pLWeapon)
  4364.                 {
  4365.                     m_pLWeapon->Hide();
  4366.                     m_pLWeapon->Term();
  4367.                     delete m_pLWeapon;
  4368.                     m_pLWeapon = NULL;
  4369.                 }
  4370.                 m_abyLWeaponID[slot] = WEAP_NONE;
  4371.             }
  4372.             // Or else check for a right handed model
  4373.             else if (m_abyWeaponID[slot] && slot == m_nCurGun)
  4374.             {
  4375.                 if(slot < 10)
  4376.                 {
  4377.                     m_NewStatusBar.UpdateWeap(0, 0, slot);
  4378.                 }
  4379.                 if (m_pWeapon)
  4380.                 {
  4381.                     m_pWeapon->Hide();
  4382.                     m_pWeapon->Term();
  4383.                     delete m_pWeapon;
  4384.                     m_pWeapon = NULL;
  4385.                 }
  4386.                 m_abyWeaponID[slot] = WEAP_NONE;
  4387.             }
  4388.         }
  4389.         break;
  4390.  
  4391.         case SMSG_CHANGEWEAPON:
  4392.         {
  4393.             DBYTE slot = pClientDE->ReadFromMessageByte(hMessage);
  4394.             ChangeWeapon(slot);
  4395.         }
  4396.         break;
  4397.  
  4398.         case SMSG_ITEMCHANGED:
  4399.         {
  4400.             DBYTE nChangeFlags;
  4401.             DBOOL bShow;
  4402.             char *pCurName;
  4403.  
  4404.             nChangeFlags = pClientDE->ReadFromMessageByte(hMessage);
  4405.             bShow = ( nChangeFlags & ITEMF_SHOWITEMS ) ? DTRUE : DFALSE;
  4406.  
  4407.             if ( nChangeFlags & ITEMF_CURRENTITEM )
  4408.             {
  4409.                 if( m_hCurrentItemName )
  4410.                 {
  4411.                     pClientDE->FreeString( m_hCurrentItemName );
  4412.                     m_hCurrentItemName = DNULL;
  4413.                 }
  4414.                 if( m_hCurrentItemIcon )
  4415.                 {
  4416.                     pClientDE->FreeString( m_hCurrentItemIcon );
  4417.                     m_hCurrentItemIcon = DNULL;
  4418.                 }
  4419.                 if( m_hCurrentItemIconH )
  4420.                 {
  4421.                     pClientDE->FreeString( m_hCurrentItemIconH );
  4422.                     m_hCurrentItemIconH = DNULL;
  4423.                 }
  4424.  
  4425.                 pCurName = pClientDE->ReadFromMessageString(hMessage);
  4426.                 if( pCurName[0] )
  4427.                 {
  4428.                     m_hCurrentItemName    = pClientDE->CreateString( pCurName );
  4429.                     m_hCurrentItemIcon    = pClientDE->ReadFromMessageHString(hMessage);
  4430.                     m_hCurrentItemIconH    = pClientDE->ReadFromMessageHString(hMessage);
  4431.                 }
  4432.             }
  4433.  
  4434.             if ( nChangeFlags & ITEMF_PREVITEM )
  4435.             {
  4436.                 if( m_hPrevItemIcon )
  4437.                     pClientDE->FreeString( m_hPrevItemIcon );
  4438.                 m_hPrevItemIcon        = pClientDE->ReadFromMessageHString(hMessage);
  4439.             }
  4440.  
  4441.             if ( nChangeFlags & ITEMF_NEXTITEM )
  4442.             {
  4443.                 if( m_hNextItemIcon )
  4444.                     pClientDE->FreeString( m_hNextItemIcon );
  4445.                 m_hNextItemIcon        = pClientDE->ReadFromMessageHString(hMessage);
  4446.             }
  4447.  
  4448.             if ( nChangeFlags & ITEMF_CURRENTITEMCHARGE )
  4449.             {
  4450.                 m_nCurrentItemCharge = pClientDE->ReadFromMessageByte(hMessage);
  4451.             }
  4452.  
  4453.             if ( nChangeFlags & ITEMF_PREVITEMCHARGE )
  4454.             {
  4455.                 m_nPrevItemCharge = pClientDE->ReadFromMessageByte(hMessage);
  4456.             }
  4457.  
  4458.             if ( nChangeFlags & ITEMF_NEXTITEMCHARGE )
  4459.             {
  4460.                 m_nNextItemCharge = pClientDE->ReadFromMessageByte(hMessage);
  4461.             }
  4462.  
  4463.             m_NewStatusBar.UpdateInv( bShow, m_hCurrentItemName, m_hCurrentItemIcon, m_hCurrentItemIconH, m_nCurrentItemCharge, m_hPrevItemIcon, m_nPrevItemCharge, m_hNextItemIcon, m_nNextItemCharge);
  4464.         }
  4465.         break;
  4466.  
  4467.         case SMSG_CONVERSATION:
  4468.         {
  4469.             GetVoiceMgr()->StopAll();
  4470.             HSTRING file = pClientDE->ReadFromMessageHString(hMessage);
  4471.             HSTRING text = pClientDE->ReadFromMessageHString(hMessage);
  4472.             DBYTE chosen = pClientDE->ReadFromMessageByte(hMessage);
  4473.             m_CommLink.StartCommunication(chosen, pClientDE->GetStringData(file), pClientDE->GetStringData(text));
  4474.             pClientDE->FreeString( file );
  4475.             pClientDE->FreeString( text );
  4476.         }
  4477.         break;
  4478.  
  4479.         case SMSG_OBJECTIVES:
  4480.         {
  4481.             if ((m_nGameType == GAMETYPE_SINGLE) || (m_nGameType == GAMETYPE_CUSTOM))
  4482.             {
  4483.                 DDWORD    resNum = pClientDE->ReadFromMessageDWord(hMessage);
  4484.  
  4485.                 if (m_hstrObjectivesText)
  4486.                 {
  4487.                     pClientDE->FreeString(m_hstrObjectivesText);
  4488.                     m_hstrObjectivesText = DNULL;
  4489.                 }
  4490.  
  4491.                 if (m_hstrObjectivesTitle)
  4492.                 {
  4493.                     pClientDE->FreeString(m_hstrObjectivesTitle);
  4494.                     m_hstrObjectivesTitle = DNULL;
  4495.                 }
  4496.  
  4497.                 if(resNum)
  4498.                 {
  4499.                     m_hstrObjectivesTitle = pClientDE->FormatString(IDS_OBJECTIVE_TITLE_1_1 + resNum - 1);
  4500.                     m_hstrObjectivesText  = pClientDE->FormatString(IDS_OBJECTIVE_1_1 + resNum - 1);
  4501.                 }
  4502.                 else
  4503.                 {
  4504.  
  4505.                     m_hstrObjectivesTitle = pClientDE->ReadFromMessageHString(hMessage);
  4506.                     m_hstrObjectivesText  = pClientDE->ReadFromMessageHString(hMessage);
  4507.                 }
  4508.  
  4509.                 m_NewStatusBar.UpdateObjectives(pClientDE->GetStringData(m_hstrObjectivesTitle), pClientDE->GetStringData(m_hstrObjectivesText));
  4510.             }
  4511.         }
  4512.         break;
  4513.  
  4514.         case SMSG_ZOOMVIEW:
  4515.         {
  4516.             m_bZoomView = pClientDE->ReadFromMessageByte(hMessage);
  4517.             DBYTE nType = pClientDE->ReadFromMessageByte(hMessage);
  4518.  
  4519.             if(m_bZoomView)
  4520.             {
  4521. //                m_fOriginalKeyTurnRate = GetKeyboardTurnRate();
  4522. //                SetKeyboardTurnRate(m_fOriginalKeyTurnRate / 4.0f);
  4523. //                m_fOriginalMouseSensitivity = GetMouseSensitivity();
  4524. //                SetMouseSensitivity(m_fOriginalMouseSensitivity / 4.0f, DTRUE);
  4525.  
  4526.                 m_bCrosshairOriginallyOn = m_bShowCrosshair;
  4527.                 m_nCrosshairOriginalNum = m_nCrosshair;
  4528.  
  4529.                 if(nType)
  4530.                 {
  4531.                     m_bShowCrosshair = DTRUE;
  4532.                     m_nCrosshair = nType;
  4533.                 }
  4534.             }
  4535.             else
  4536.             {
  4537. //                SetKeyboardTurnRate(m_fOriginalKeyTurnRate);
  4538. //                SetMouseSensitivity(m_fOriginalMouseSensitivity);
  4539.                 m_bShowCrosshair = m_bCrosshairOriginallyOn;
  4540.                 m_nCrosshair = m_nCrosshairOriginalNum;
  4541.             }
  4542.         }
  4543.         break;
  4544.  
  4545.         case SMSG_ADDPLAYER:
  4546.         {
  4547.             if (IsMultiplayerGame())
  4548.             {
  4549.                 HSTRING hstrName = pClientDE->ReadFromMessageHString (hMessage);
  4550.                 DDWORD nID = pClientDE->ReadFromMessageDWord (hMessage);
  4551.                 DBYTE byCharacter  = pClientDE->ReadFromMessageByte (hMessage);
  4552.                 int nFrags = (int) pClientDE->ReadFromMessageFloat (hMessage);
  4553.                 DBYTE byTeamID = pClientDE->ReadFromMessageByte (hMessage);
  4554.  
  4555.                 if (m_FragInfo.GetClientInfo(nID))
  4556.                 {
  4557.                     pClientDE->FreeString(hstrName);
  4558.                     return;
  4559.                 }
  4560.  
  4561.                 m_FragInfo.AddClient (hstrName, nID, nFrags, byCharacter);
  4562.  
  4563.                 DDWORD dwLocalID = 0;
  4564.                 pClientDE->GetLocalClientID(&dwLocalID);
  4565.                 if (dwLocalID == nID)
  4566.                 {
  4567.                     m_NewStatusBar.SetTeamID((int)byTeamID);
  4568.                 }
  4569.  
  4570.                 m_TeamMgr.AddPlayer(byTeamID, nID);
  4571.                 m_TeamMgr.AddPlayerFrags(byTeamID, nID, nFrags);
  4572.                 CTeam* pTeam = m_TeamMgr.GetTeam(byTeamID);
  4573.  
  4574.                 if (IsMultiplayerTeamBasedGame() && pTeam)
  4575.                 {
  4576.                     HSTRING hStr = pClientDE->FormatString(IDS_ADDPLAYERTEAM, pClientDE->GetStringData(hstrName), pTeam->GetName());
  4577.                     CSPrint(pClientDE->GetStringData(hStr));
  4578.                     pClientDE->FreeString (hStr);
  4579.                 }
  4580.                 else
  4581.                 {
  4582.                     HSTRING hStr = pClientDE->FormatString (IDS_ADDPLAYER, pClientDE->GetStringData (hstrName));
  4583.                     CSPrint (pClientDE->GetStringData (hStr));
  4584.                     pClientDE->FreeString (hStr);
  4585.                 }
  4586.  
  4587.                 pClientDE->FreeString(hstrName);
  4588.             }
  4589.         }
  4590.         break;
  4591.  
  4592.         case SMSG_REMOVEPLAYER:
  4593.         {
  4594.             if (IsMultiplayerGame())
  4595.             {
  4596.                 DDWORD nID   = pClientDE->ReadFromMessageDWord(hMessage);
  4597.                 char*  sName = m_FragInfo.GetPlayerName(nID);
  4598.  
  4599.                 if (sName && strlen(sName) > 0)
  4600.                 {
  4601.                     DDWORD dwLocalID = 0xFFFFFFFF;
  4602.                     pClientDE->GetLocalClientID(&dwLocalID);
  4603.  
  4604.                     if (dwLocalID != nID)
  4605.                     {
  4606.                         HSTRING hStr = pClientDE->FormatString(IDS_REMOVEPLAYER, sName);
  4607.                         CSPrint (pClientDE->GetStringData(hStr));
  4608.                         pClientDE->FreeString(hStr);
  4609.                     }
  4610.                 }
  4611.                 
  4612.                 m_FragInfo.RemoveClient (nID);
  4613.                 m_TeamMgr.RemovePlayer(nID);
  4614.  
  4615.                 if (g_bLevelChange3rdPersonCam)
  4616.                 {
  4617.                     g_bLevelChangeNoUpdate = DTRUE;
  4618.                 }
  4619.             }
  4620.         }
  4621.         break;
  4622.  
  4623.         case SMSG_PLAYER_FRAGGED:
  4624.         {
  4625.             if (IsMultiplayerGame())
  4626.             {
  4627.                 DDWORD nLocalID = 0;
  4628.                 _mbscpy((unsigned char*)msgbuf, (const unsigned char*)"");
  4629.                 pClientDE->GetLocalClientID (&nLocalID);
  4630.  
  4631.                 DDWORD nVictim = pClientDE->ReadFromMessageDWord (hMessage);
  4632.                 DDWORD nKiller = pClientDE->ReadFromMessageDWord (hMessage);
  4633.                 D_WORD wIndex = pClientDE->ReadFromMessageWord (hMessage);
  4634.  
  4635.                 AssignFrags(nLocalID, nVictim, nKiller);
  4636.  
  4637.                 VoiceEntry *pve = DNULL;
  4638.  
  4639.                 char *pKiller = m_FragInfo.GetPlayerName(nKiller);
  4640.                 char *pVictim = m_FragInfo.GetPlayerName(nVictim);
  4641.  
  4642.                 if (pKiller && pVictim)
  4643.                 {
  4644.                     DBYTE byFlags = 0;
  4645.                     switch(m_FragInfo.GetPlayerCharacter(nKiller))
  4646.                     {
  4647.                         case CHARACTER_GABREILLA:
  4648.                         case CHARACTER_OPHELIA:
  4649.                             byFlags |= VOICEFLAG_FEMALE_ATTACKER;
  4650.                             break;
  4651.                         default:
  4652.                             byFlags |= VOICEFLAG_MALE_ATTACKER;
  4653.                             break;
  4654.                     }
  4655.                     
  4656.                     switch(m_FragInfo.GetPlayerCharacter(nVictim))
  4657.                     {
  4658.                         case CHARACTER_GABREILLA:
  4659.                         case CHARACTER_OPHELIA:
  4660.                             byFlags |= VOICEFLAG_FEMALE_VICTIM;
  4661.                             break;
  4662.                         default:
  4663.                             byFlags |= VOICEFLAG_MALE_VICTIM;
  4664.                             break;
  4665.                     }
  4666.                     
  4667.                     // Display a message
  4668.                     if (nVictim == nKiller)        // Suicide
  4669.                     {
  4670.                         pve = GetVoiceEntry(g_aVoiceSuicide, 
  4671.                                             NUM_VOICE_SUICIDE, 
  4672.                                             wIndex, 
  4673.                                             byFlags);
  4674.     //                    pve = &g_aVoiceSuicide[wIndex % NUM_VOICE_SUICIDE]; 
  4675.                         if (pve)
  4676.                             sprintf(msgbuf, pve->m_szText, pKiller);
  4677.                     }
  4678.                     else                        // Frag
  4679.                     {
  4680.                         pve = GetVoiceEntry(g_aVoiceKill, 
  4681.                                             NUM_VOICE_KILL, 
  4682.                                             wIndex, 
  4683.                                             byFlags);
  4684.     //                    pve = &g_aVoiceKill[wIndex % NUM_VOICE_KILL]; 
  4685.                         if (pve)
  4686.                             sprintf(msgbuf, pve->m_szText, pKiller, pVictim);
  4687.                     }
  4688.  
  4689.                     if (nKiller == nLocalID)
  4690.                     {
  4691.                         char szSoundFile[MAX_CS_FILENAME_LEN];
  4692.                         _mbscpy((unsigned char*)szSoundFile, (const unsigned char*)"Sounds\\Voice\\");
  4693.                         _mbscat((unsigned char*)szSoundFile, (const unsigned char*)pve->m_szFile);
  4694.                         m_CommLink.StartCommunication(4, szSoundFile, msgbuf);
  4695.                     }
  4696.                     else 
  4697.                         CSPrint(msgbuf);
  4698.                 }
  4699.             }
  4700.         }
  4701.         break;
  4702.  
  4703.         case SMSG_GRABBEDTHEFLAG:
  4704.         {
  4705.             DisplayStatusBarFlagIcon(DTRUE);
  4706.             PlaySound("sounds_multipatch\\CtfFlagGrab.wav");
  4707.             CSPrint(IDS_CTF_GRABBED);
  4708.             break;
  4709.         }
  4710.  
  4711.         case SMSG_RETURNEDTHEFLAG:
  4712.         {
  4713.             PlaySound("sounds_multipatch\\CtfFlagGrab.wav");
  4714.             CSPrint(IDS_CTF_RETURNED);
  4715.             break;
  4716.         }
  4717.  
  4718.         case SMSG_DROPPEDTHEFLAG:
  4719.         {
  4720.             DisplayStatusBarFlagIcon(DFALSE);
  4721.             break;
  4722.         }
  4723.  
  4724.         case SMSG_NEEDYOURFLAG:
  4725.         {
  4726.             static DFLOAT fLastTime = 0;
  4727.             DFLOAT fCurTime = g_pClientDE->GetTime();
  4728.  
  4729.             if ((fLastTime + 20) < fCurTime)
  4730.             {
  4731.                 CSPrint(IDS_CTF_RETURNYOURFLAG);
  4732.                 fLastTime = fCurTime;
  4733.             }
  4734.             break;
  4735.         }
  4736.  
  4737.         case SMSG_CAPTUREDTHEFLAG:
  4738.         {
  4739.             DisplayStatusBarFlagIcon(DFALSE);
  4740.  
  4741.             DDWORD dwLocalID = 0;
  4742.             pClientDE->GetLocalClientID(&dwLocalID);
  4743.  
  4744.             DDWORD dwFlagger = pClientDE->ReadFromMessageDWord(hMessage);
  4745.             int    nFrags    = (int)pClientDE->ReadFromMessageDWord(hMessage);
  4746.  
  4747.             m_FragInfo.AddFrags(dwLocalID, dwFlagger, nFrags);
  4748.             m_TeamMgr.AddPlayerFrags(dwFlagger, nFrags);
  4749.  
  4750.             char* sFlagger = m_FragInfo.GetPlayerName(dwFlagger);
  4751.             if (sFlagger)
  4752.             {
  4753.                 char sMsg[256];
  4754.                 CTeam* pTeam = m_TeamMgr.GetTeamFromPlayerID(dwFlagger);
  4755.                 if (pTeam) sprintf(sMsg, pClientDE->GetStringData(m_hCtfCapturedString1), sFlagger, pTeam->GetName());
  4756.                 else sprintf(sMsg, pClientDE->GetStringData(m_hCtfCapturedString2), sFlagger);
  4757.  
  4758.                 if (dwLocalID == dwFlagger)
  4759.                 {
  4760.                     CSPrint(IDS_CTF_CAPTURED_3);
  4761.                 }
  4762.                 else
  4763.                 {
  4764.                     CSPrint(sMsg);
  4765.                 }
  4766.             }
  4767.         }
  4768.         break;
  4769.  
  4770. #ifdef _ADDON
  4771.         case SMSG_SOCCERGOAL:
  4772.         {
  4773.             DDWORD dwLocalID, dwScorer;
  4774.             int nFrags;
  4775.             DBYTE nTeamID;
  4776.             char *sScorer;
  4777.             char sMsg[256];
  4778.             CTeam *pTeam;
  4779.             char *pszSound;
  4780.  
  4781.             DisplayStatusBarFlagIcon(DFALSE);
  4782.  
  4783.             dwLocalID = 0;
  4784.             pClientDE->GetLocalClientID(&dwLocalID);
  4785.  
  4786.             dwScorer = pClientDE->ReadFromMessageDWord(hMessage);
  4787.             nFrags = (int)pClientDE->ReadFromMessageDWord(hMessage);
  4788.             nTeamID = pClientDE->ReadFromMessageByte( hMessage );
  4789.  
  4790.             m_FragInfo.AddFrags( dwLocalID, dwScorer, nFrags );
  4791.             m_TeamMgr.AddPlayerFrags( dwScorer, nFrags );
  4792.  
  4793.             pszSound = DNULL;
  4794.             if( nFrags >= 0 )
  4795.             {
  4796.                 pszSound = s_szCheerSounds[ GetRandom( 0, NUMCHEERSOUNDS - 1 ) ];
  4797.             }
  4798.             else
  4799.             {
  4800.                 pszSound = s_szBooSounds[ GetRandom( 0, NUMBOOSOUNDS - 1 ) ];
  4801.             }
  4802.             if( pszSound )
  4803.                 PlaySoundLocal( pszSound, SOUNDPRIORITY_MISC_MEDIUM );
  4804.  
  4805.             if( dwLocalID == dwScorer )
  4806.             {
  4807.                 // Made a good goal
  4808.                 if( nFrags >= 0 )
  4809.                     CSPrint(IDS_SOCCER_GOAL_3);
  4810.                 // Wrong goal!
  4811.                 else
  4812.                     CSPrint(IDS_SOCCER_GOAL_4);
  4813.             }
  4814.             else
  4815.             {
  4816.                 sScorer = m_FragInfo.GetPlayerName( dwScorer );
  4817.                 if( sScorer )
  4818.                 {
  4819.                     pTeam = m_TeamMgr.GetTeam(( nTeamID == TEAM_1 ) ? TEAM_2 : TEAM_1 );
  4820.                     if( pTeam )
  4821.                         sprintf( sMsg, pClientDE->GetStringData( m_hSoccerGoalString1 ), sScorer, pTeam->GetName( ));
  4822.                     else
  4823.                         sprintf( sMsg, pClientDE->GetStringData( m_hSoccerGoalString2 ), sScorer );
  4824.     
  4825.                     CSPrint(sMsg);
  4826.                 }
  4827.             }
  4828.         }
  4829.         break;
  4830.  
  4831.         case SMSG_TRAPPED:
  4832.         {
  4833.             m_nTrapped = (int)pClientDE->ReadFromMessageByte(hMessage);
  4834.             DBYTE byType = pClientDE->ReadFromMessageByte(hMessage);
  4835.         }
  4836.         break;
  4837.  
  4838. #endif // _ADDON
  4839.  
  4840.         case SMSG_THEVOICE:
  4841.         {
  4842.             if (IsMultiplayerGame())
  4843.             {
  4844.                 TheVoice eVoice        = (TheVoice)pClientDE->ReadFromMessageByte(hMessage);
  4845.                 D_WORD  wIndex        = pClientDE->ReadFromMessageWord(hMessage);
  4846.                 DBYTE    byFlags        = pClientDE->ReadFromMessageByte(hMessage);
  4847.                 
  4848.                 VoiceEntry *pve = DNULL;
  4849.                 switch(eVoice)
  4850.                 {
  4851.                     case VOICE_START_BB:
  4852.                         pve = GetVoiceEntry(g_aVoiceStartBB, 
  4853.                                             NUM_VOICE_START_BB, 
  4854.                                             wIndex, 
  4855.                                             byFlags);
  4856.                         break;
  4857.  
  4858.                     case VOICE_START_CTF:
  4859.                         pve = GetVoiceEntry(g_aVoiceStartCTF, 
  4860.                                             NUM_VOICE_START_CTF, 
  4861.                                             wIndex, 
  4862.                                             byFlags);
  4863.                         break;
  4864.  
  4865.                     case VOICE_FINISHHIM:
  4866.                         pve = GetVoiceEntryWithExtraChecks(g_aVoiceHumiliation, 
  4867.                                             NUM_VOICE_HUMILIATION, 
  4868.                                             wIndex, 
  4869.                                             byFlags);
  4870.                         break;
  4871.                 }
  4872.  
  4873.                 if (pve)
  4874.                 {
  4875.                     sprintf(msgbuf, "Sounds\\Voice\\%s", pve->m_szFile);
  4876.                     m_CommLink.StartCommunication(4, msgbuf, pve->m_szText);
  4877.                 }
  4878.             }
  4879.         }
  4880.         break;
  4881.  
  4882.         case SMSG_MP_CHANGING_LEVELS :
  4883.         {
  4884.             // we're about to change levels - we don't really care if we're not in a multiplayer game
  4885.             if (!IsMultiplayerGame()) return;
  4886.  
  4887.             pClientDE->SetInputState(DFALSE);
  4888.  
  4889.             if (!m_b3rdPerson)
  4890.                 Set3rdPersonCamera(DTRUE);
  4891.  
  4892.             CSPrint(IDS_MP_CHANGINGLEVELS);
  4893.             PlaySound("sounds\\events\\bellding1.wav");
  4894.  
  4895.             m_bDrawFragBar = DTRUE;
  4896.             g_bLevelChange3rdPersonCam = DTRUE;
  4897.  
  4898.             m_bZoomView = DFALSE;
  4899.             m_bShowCrosshair = m_bCrosshairOriginallyOn;
  4900.             m_nCrosshair = m_nCrosshairOriginalNum;
  4901.  
  4902.             m_bBlind = DFALSE;
  4903.             m_nTrapped = 0;
  4904.  
  4905.             // Reset the inventory tabs
  4906.             m_NewStatusBar.UpdateInv(0, 0, 0, 0, 0, 0, 0, 0, 0);
  4907.  
  4908.             // Handle clearing out data for movement and weapon states
  4909.             m_pMoveMgr->ClearControlFlags();
  4910.             if (m_pWeapon)        m_pWeapon->CancelFiringState();
  4911.             if (m_pLWeapon)        m_pLWeapon->CancelFiringState();
  4912.         }
  4913.         break;
  4914.  
  4915.         case SMSG_EXITWORLD:
  4916.         {
  4917.             HandleExitWorld(hMessage);
  4918.  
  4919.             // Reset the inventory tabs
  4920.             m_NewStatusBar.UpdateInv(0, 0, 0, 0, 0, 0, 0, 0, 0);
  4921.         }
  4922.         break;
  4923.  /*           
  4924.         case SMSG_CUTSCENE_START :
  4925.         {
  4926.             GetVoiceMgr()->StopAll();
  4927.             m_bDrawStatusBar = DFALSE;
  4928.         }
  4929.         break;
  4930.             
  4931.         case SMSG_CUTSCENE_END :
  4932.         {
  4933.             m_bSpectatorMode = DFALSE;
  4934.             m_pExternalCamera = DNULL;
  4935.  
  4936.             m_bRenderCamera = DFALSE;
  4937.  
  4938.             if (m_pWeapon[m_nCurGun])
  4939.                 m_pWeapon[m_nCurGun]->Show();
  4940.             if (m_pLWeapon[m_nCurGun])
  4941.                 m_pLWeapon[m_nCurGun]->Show();
  4942.             
  4943.             // Turn on the Status bar
  4944.             m_bDrawStatusBar = DTRUE;
  4945.             
  4946.             m_bRenderCamera = DTRUE;
  4947.         }
  4948.         break;
  4949. */
  4950.             
  4951.         case SMSG_BURN :
  4952.         {
  4953.             DFLOAT fTheTime = pClientDE->ReadFromMessageFloat(hMessage);
  4954.             if (fTheTime > 0.0f)
  4955.             {
  4956.                 m_bBurn = DTRUE;
  4957.                 m_fBurnTime = pClientDE->GetTime() + fTheTime;
  4958.             }
  4959.             else
  4960.             {
  4961.                 m_bBurn = DFALSE;
  4962.             }
  4963.         }
  4964.         break;
  4965.         
  4966.         
  4967.         case SMSG_BLIND:
  4968.         {
  4969.             if (m_bDead)    // [blg] don't go blind if we're already dead
  4970.             {
  4971.                 m_bBlind = DFALSE;
  4972.                 return;
  4973.             }
  4974.  
  4975.             DFLOAT fTheTime = pClientDE->ReadFromMessageFloat(hMessage);
  4976.             
  4977.             if (fTheTime > 0.0f)
  4978.             {
  4979.                 HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_BLIND);
  4980.                 CSPrint(pClientDE->GetStringData(szErrorStr));
  4981.                 pClientDE->FreeString(szErrorStr);
  4982.  
  4983.                 m_bBlind     = DTRUE;
  4984.                 m_fBlindTime = pClientDE->GetTime() + fTheTime;
  4985.             }
  4986.             else
  4987.             {
  4988.                 m_bBlind = DFALSE;
  4989.             }
  4990.         }
  4991.         break;
  4992.             
  4993.             
  4994.         case SMSG_ALL_SEEING_EYE:
  4995.         {
  4996.             DBOOL bOn = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  4997.             HLOCALOBJ hObj = pClientDE->ReadFromMessageObject(hMessage);
  4998.             
  4999.             // Kill any old instance of the sound...
  5000.             if( m_hTheEyeLoopingSound )
  5001.             {
  5002.                 pClientDE->KillSound( m_hTheEyeLoopingSound );
  5003.                 m_hTheEyeLoopingSound = DNULL;
  5004.             }
  5005.  
  5006.             if (bOn && hObj)
  5007.             {
  5008.                 m_hSeeingEyeObj = hObj;
  5009.                 pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE);
  5010.                 m_hTheEyeLoopingSound = PlaySoundLocal("sounds\\powerups\\eyeloop1.wav", 
  5011.                     SOUNDPRIORITY_MISC_HIGH, DTRUE, DTRUE );
  5012.             }
  5013.             else
  5014.             {
  5015.                 m_hSeeingEyeObj = DNULL;
  5016.             }                
  5017.         }
  5018.         break;
  5019.           
  5020.         case SMSG_ORBCAM:
  5021.         {
  5022.             m_hOrbObj = DNULL;
  5023.         }
  5024.         break;
  5025.           
  5026.             
  5027.         case SMSG_DISPLAYTEXT:
  5028.         {   
  5029.             DFLOAT fTime = pClientDE->ReadFromMessageFloat(hMessage);        
  5030.             CSPrint(pClientDE->ReadFromMessageString(hMessage));
  5031.         
  5032.         // Need to send the Font, Height, Color, Position on the Screen x,y
  5033.         //    
  5034.         //        m_hFont = pClientDE->CreateFont("Arial", 6, 16, DFALSE, DFALSE, DFALSE);
  5035.         //        m_nFontHeight = 16;
  5036.         //        HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE);
  5037.         //        hSurface = pClientDE->CreateSurfaceFromString (m_hFont, hMsg, hForeground, NULL, 10, 0);
  5038.         //        if (hSurface)  // Error
  5039.         //        {
  5040.         //            return;
  5041.         //        }
  5042.             
  5043.         }   
  5044.         break;
  5045.          
  5046.  
  5047.  
  5048.         case SMSG_SCREENFADE:
  5049.         {
  5050.             DBYTE m_nFadeMode = pClientDE->ReadFromMessageByte(hMessage);
  5051.             if (m_nFadeMode == 1)
  5052.             {
  5053.                 m_bFadeIn = DTRUE;
  5054.                 m_bFadeOut = DFALSE;
  5055.                 m_fFadeVal = 0.0f;
  5056.             }
  5057.             else
  5058.             {
  5059.                 m_bFadeOut = DTRUE;
  5060.                 m_bFadeIn = DFALSE;
  5061.                 m_fFadeVal = 255.0f;
  5062.             }
  5063.         }    
  5064.         break;
  5065.  
  5066. /*        case SMSG_STONEVIEW:
  5067.         {
  5068.             m_bStoneView = pClientDE->ReadFromMessageByte(hMessage);
  5069.             break;
  5070.         }
  5071.             
  5072.         case SMSG_AURAVIEW:
  5073.         {
  5074.             m_bAuraView = pClientDE->ReadFromMessageByte(hMessage);
  5075.             if (m_bAuraView)
  5076.                 pClientDE->SetModelHook ((ModelHookFn)AuraModelHook, pClientDE);
  5077.             else
  5078.                 pClientDE->SetModelHook (DNULL, DNULL);
  5079.             break;
  5080.         }
  5081. */
  5082.         case SMSG_FORCEROTATION:
  5083.         {
  5084.             m_fPitch = pClientDE->ReadFromMessageFloat(hMessage);
  5085.             m_fYaw = pClientDE->ReadFromMessageFloat(hMessage);
  5086.             break;
  5087.         }
  5088.  
  5089.  
  5090.         case SMSG_MUSIC:
  5091.         {
  5092.             if( m_Music.IsInitialized( ))
  5093.             {
  5094.                 m_Music.HandleMusicMessage( hMessage );
  5095.                 m_eMusicLevel = m_Music.GetMusicLevel( );
  5096.             }
  5097.             break;
  5098.         }
  5099.  
  5100.         // Returned when the server has successfully saved a game
  5101.         // Copy save data from the Current slot into the 
  5102.         case SMSG_SAVEGAME_ACK:
  5103.         {
  5104.             if (GetGameState() == GS_SAVING)
  5105.             {
  5106.                 // Save the current world filename for future restoration
  5107.                 int nSlot = m_SavedGameInfo.GetReservedSlot();
  5108.                 if (nSlot == SLOT_QUICK)
  5109.                     _mbscpy((unsigned char*)m_SavedGameInfo.gQuickSaveInfo.szCurrentLevel, (const unsigned char*)m_szFilename);
  5110.                 else
  5111.                     _mbscpy((unsigned char*)m_SavedGameInfo.gSaveSlotInfo[nSlot].szCurrentLevel, (const unsigned char*)m_szFilename);
  5112.  
  5113.                 if (nSlot != SLOT_NONE)
  5114.                 {
  5115.                     m_SavedGameInfo.CopySlot(SLOT_CURRENT, nSlot);
  5116.                     m_SavedGameInfo.SetSlotName(nSlot, DNULL);
  5117.                     m_SavedGameInfo.SaveInfo(nSlot, m_nGameType, GetCharacter());
  5118.                 }
  5119.                 m_SavedGameInfo.SetReservedSlot(SLOT_NONE);
  5120.  
  5121.                 SetGameState(GS_PLAYING); 
  5122.                 PauseGame(DFALSE);
  5123.             }
  5124.             break;
  5125.         }
  5126.  
  5127.         // Successfully loaded a world, keep track of it for autosave
  5128.         case SMSG_LOADWORLD_ACK:
  5129.         {
  5130.             DBOOL bSuccess = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  5131.  
  5132.             if (bSuccess)
  5133.             {
  5134.                 // Set the world name
  5135.                 if (m_hstrTitle)
  5136.                     m_SavedGameInfo.SetSlotName(SLOT_CURRENT, pClientDE->GetStringData(m_hstrTitle));
  5137.  
  5138.                 // Save the current world filename for future restoration
  5139.                 _mbscpy((unsigned char*)m_SavedGameInfo.gCurrentSaveInfo.szCurrentLevel, (const unsigned char*)m_szFilename);
  5140.                 m_SavedGameInfo.SaveInfo(SLOT_CURRENT, m_nGameType, GetCharacter());
  5141.             }
  5142.             else  // Abort! Abort!
  5143.             {
  5144.                 SetGameState(GS_MENU);
  5145. //                pClientDE->Disconnect();
  5146.             }
  5147.             break;
  5148.         }
  5149.  
  5150.         case SMSG_CLIENTSAVEDATA:
  5151.         {
  5152.             LoadClientData( hMessage );
  5153.             break;
  5154.         }
  5155.  
  5156.         case SMSG_PLAYERINIT_SINGLEPLAYER:
  5157.         {
  5158.             InitSinglePlayer();
  5159.         }
  5160.         break;
  5161.  
  5162.         case SMSG_PLAYERINIT_MULTIPLAYER:
  5163.         {
  5164.             BYTE byGameType = pClientDE->ReadFromMessageByte(hMessage);
  5165.             m_nGameType = byGameType;
  5166.  
  5167.             m_bNetFriendlyFire   = pClientDE->ReadFromMessageByte(hMessage);
  5168.             m_bNetNegTeamFrags   = pClientDE->ReadFromMessageByte(hMessage);
  5169.             m_bNetOnlyFlagScores = pClientDE->ReadFromMessageByte(hMessage);
  5170.             m_bNetOnlyGoalScores = pClientDE->ReadFromMessageByte(hMessage);
  5171.  
  5172.             InitMultiPlayer();
  5173.  
  5174.             if (m_pWeapon)        m_pWeapon->CancelFiringState();
  5175.             if (m_pLWeapon)        m_pLWeapon->CancelFiringState();
  5176.         }
  5177.         break;
  5178.  
  5179.         case SMSG_THIEF_ATTACH:
  5180.         {
  5181.             HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage);
  5182.             HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage);
  5183.  
  5184.             if(m_pCreature && hServObj && hEnemyObj)
  5185.             {
  5186.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI);
  5187.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5188.                 pClientDE->EndMessage(hMessage);
  5189.             }
  5190.             else
  5191.             {
  5192.                 m_pCreature = new CViewCreature;
  5193.                 m_pCreature->Create(pClientDE, SMSG_THIEF_ATTACH, hServObj, hEnemyObj);
  5194.  
  5195.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK);
  5196.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5197.                 pClientDE->EndMessage(hMessage);
  5198.             }
  5199.  
  5200.             break;
  5201.         }
  5202.  
  5203.         case SMSG_HAND_ATTACH:
  5204.         {
  5205.             HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage);
  5206.             HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage);
  5207.  
  5208.             if(m_pCreature && hServObj && hEnemyObj)
  5209.             {
  5210.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI);
  5211.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5212.                 pClientDE->EndMessage(hMessage);
  5213.             }
  5214.             else
  5215.             {
  5216.                 m_pCreature = new CViewCreature;
  5217.                 m_pCreature->Create(pClientDE, SMSG_HAND_ATTACH, hServObj, hEnemyObj);
  5218.  
  5219.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK);
  5220.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5221.                 pClientDE->EndMessage(hMessage);
  5222.             }
  5223.  
  5224.             break;
  5225.         }
  5226.  
  5227.         case SMSG_BONELEECH_ATTACH:
  5228.         {
  5229.             HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage);
  5230.             HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage);
  5231.  
  5232.             if(m_pCreature && hServObj && hEnemyObj)
  5233.             {
  5234.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI);
  5235.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5236.                 pClientDE->EndMessage(hMessage);
  5237.             }
  5238.             else
  5239.             {
  5240.                 m_pCreature = new CViewCreature;
  5241.                 m_pCreature->Create(pClientDE, SMSG_BONELEECH_ATTACH, hServObj, hEnemyObj);
  5242.  
  5243.                 HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK);
  5244.                 pClientDE->WriteToMessageObject(hMessage, hServObj);
  5245.                 pClientDE->EndMessage(hMessage);
  5246.             }
  5247.  
  5248.             break;
  5249.         }
  5250.  
  5251.         case SMSG_DETACH_AI:
  5252.         {
  5253.             if(m_pCreature)
  5254.             {
  5255.                 m_pCreature->Detach();
  5256.             }
  5257.  
  5258.             break;
  5259.         }
  5260.  
  5261.         case SMSG_DEAD:
  5262.         {
  5263.             // Just died..
  5264.             m_bDead  = DTRUE;
  5265.             m_bBlind = DFALSE;
  5266.             m_nTrapped = 0;
  5267.             m_playerCamera.GoDeathMode();
  5268.  
  5269.             if (IsWonkyNoMove()) m_bDeadNoHide = DTRUE;
  5270.             EndWonkyVision();
  5271.  
  5272.             if(IsMultiplayerGame())
  5273.                 m_bDrawFragBar = DTRUE;
  5274.         }
  5275.         break;
  5276.  
  5277.         case SMSG_WONKYVISION:        // Set to WonkyVision for a period of time.
  5278.         {
  5279.             DFLOAT fWonkyTime   = pClientDE->ReadFromMessageFloat(hMessage); 
  5280.             DBYTE  bWonkyNoMove = pClientDE->ReadFromMessageByte(hMessage); 
  5281.  
  5282.             if (m_bDead) fWonkyTime = 0;    // [blg] no wonky if we're dead!
  5283.  
  5284.             if (fWonkyTime > m_fWonkyTime)
  5285.             {
  5286.                 if (bWonkyNoMove) CSPrint(IDS_EDGEOFDEATH);
  5287.                 StartWonkyVision(fWonkyTime, bWonkyNoMove);
  5288.             }
  5289.             else if (fWonkyTime == 0)
  5290.             {
  5291.                 EndWonkyVision();
  5292.             }
  5293.  
  5294.             break;
  5295.         }
  5296.  
  5297.         case SMSG_VOICEMGR:
  5298.         {
  5299.             DBOOL bEvent     = (DBOOL)pClientDE->ReadFromMessageByte(hMessage);
  5300.             int   iCharacter = (int)pClientDE->ReadFromMessageWord(hMessage);
  5301.             int   iEvent     = (int)pClientDE->ReadFromMessageWord(hMessage);
  5302.  
  5303.             if (bEvent)
  5304.             {
  5305.                 GetVoiceMgr()->PlayEventSound(iCharacter, iEvent);
  5306.             }
  5307.             else
  5308.             {
  5309.                 GetVoiceMgr()->PlayUniqueSound(iCharacter, iEvent);
  5310.             }
  5311.  
  5312.             break;
  5313.         }
  5314.  
  5315.         case SMSG_VOICEMGR_STOPALL:
  5316.         {
  5317.             GetVoiceMgr()->StopAll();
  5318.             break;
  5319.         }
  5320.  
  5321.         case SMSG_INVITEMACTION:
  5322.         {
  5323.             DBYTE nType;
  5324.             DBOOL bActivate;
  5325.  
  5326.             nType = g_pClientDE->ReadFromMessageByte( hMessage );
  5327.             bActivate = ( nType & 0x80 );
  5328.             nType &= 0x7F;
  5329.  
  5330.             HandleInvAction( nType, bActivate );
  5331.             break;
  5332.         }
  5333.  
  5334. /*        case SMSG_WEAPONHANDMODEL:
  5335.         {
  5336.             HLOCALOBJ hObj = g_pClientDE->ReadFromMessageObject(hMessage);
  5337.             DBOOL bLeft = g_pClientDE->ReadFromMessageByte(hMessage);
  5338.             DBOOL bVisible = g_pClientDE->ReadFromMessageByte(hMessage);
  5339.  
  5340.             if (!hObj) break;
  5341.  
  5342.             DDWORD dwFlags = pClientDE->GetObjectFlags(hObj);
  5343.             if (bVisible)
  5344.             {
  5345.                 pClientDE->SetObjectFlags(hObj, dwFlags | FLAG_VISIBLE);
  5346.                 pClientDE->SetObjectClientFlags(hObj, 0);
  5347.             }
  5348.             else
  5349.             {
  5350.                 pClientDE->SetObjectFlags(hObj, dwFlags & ~FLAG_VISIBLE);
  5351.                 pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE);
  5352.             }
  5353.  
  5354.             if (bLeft)        m_hLWeapHandObj    = (bVisible) ? NULL : hObj;
  5355.                 else        m_hWeapHandObj    = (bVisible) ? NULL : hObj;
  5356.  
  5357.             break;
  5358.         }*/
  5359.  
  5360.         case SMSG_DOAUTOSAVE:
  5361.         {
  5362.             MenuSaveGame(SLOT_NONE, SAVETYPE_AUTO);
  5363.         }
  5364.         break;
  5365.     }
  5366. }
  5367.  
  5368.  
  5369.  
  5370. // --------------------------------------------------------------------------- //
  5371. //
  5372. //    ROUTINE:    CBloodClientShell::InitSinglePlayer
  5373. //
  5374. //    PURPOSE:    Initializes a single player game
  5375. //
  5376. // --------------------------------------------------------------------------- //
  5377.  
  5378. void CBloodClientShell::InitSinglePlayer()
  5379. {
  5380.     CClientDE* pClientDE = GetClientDE();
  5381.     if (!pClientDE) return;
  5382.  
  5383.     // Init player info only on the first world...
  5384.     if (m_bFirstWorld)
  5385.         SendPlayerInitMessage(CMSG_SINGLEPLAYER_INIT);
  5386.  
  5387.     // Send autosave message
  5388.     HMESSAGEWRITE hWrite = pClientDE->StartMessage(CMSG_AUTOSAVE);
  5389.     pClientDE->EndMessage(hWrite);
  5390.  
  5391.     if(m_bPaused)    SetGameState(GS_WAITING);
  5392.         else        SetGameState(GS_PLAYING);
  5393.  
  5394.     pClientDE->SetInputState(DTRUE);
  5395. }
  5396.  
  5397.  
  5398. // --------------------------------------------------------------------------- //
  5399. //
  5400. //    ROUTINE:    CBloodClientShell::InitMultiPlayer
  5401. //
  5402. //    PURPOSE:    Send the server the initial player info
  5403. //
  5404. // --------------------------------------------------------------------------- //
  5405.  
  5406. void CBloodClientShell::InitMultiPlayer()
  5407. {
  5408.     CClientDE* pClientDE = GetClientDE();
  5409.     if (!pClientDE) return;
  5410.  
  5411.     // Init multiplayer info on server...
  5412.     SendPlayerInitMessage(CMSG_MULTIPLAYER_INIT);
  5413.  
  5414.     SetGameState(GS_PLAYING);
  5415.     pClientDE->SetInputState (DTRUE);
  5416. }
  5417.  
  5418.  
  5419. // --------------------------------------------------------------------------- //
  5420. //
  5421. //    ROUTINE:    CBloodClientShell::UpdateGun()
  5422. //
  5423. //    PURPOSE:    Updates the view gun info
  5424. //
  5425. // --------------------------------------------------------------------------- //
  5426. void CBloodClientShell::UpdateGun(DRotation *rot, DVector *pos)
  5427. {
  5428.     CClientDE* pClientDE = GetClientDE();
  5429.  
  5430.     // Determine whether we should be showing the weapon or not.
  5431.     // Hide gun if spectator mode, or health is 0.
  5432.     if (m_bSpectatorMode || m_bDead || !m_playerCamera.IsFirstPerson() || m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj )
  5433.     {
  5434.         if (m_pWeapon) m_pWeapon->Hide();
  5435.         if (m_pLWeapon) m_pLWeapon->Hide();
  5436.     }
  5437.     else
  5438.     {
  5439.         if (m_pWeapon) m_pWeapon->Show();
  5440.         if (m_pLWeapon) m_pLWeapon->Show();
  5441.     }
  5442.  
  5443.     if (!m_bSpectatorMode)
  5444.     {
  5445.         DVector vGunMuzzlePos, vPos;
  5446.  
  5447.         if (m_pWeapon)
  5448.         {
  5449.             m_pWeapon->UpdateBob(m_fSwayHeight + m_fWeaponY, m_fSwayWidth);
  5450.             m_pWeapon->Update(cdata.fPitch, cdata.fYaw, pos);
  5451.  
  5452.             pClientDE->GetObjectPos(pClientDE->GetClientObject(), &vPos);
  5453.             VEC_COPY(vGunMuzzlePos, m_pWeapon->GetMuzzlePos());
  5454.             VEC_SUB(cdata.GunMuzzlePos, vGunMuzzlePos, vPos);
  5455.         }
  5456.         if (m_pLWeapon)
  5457.         {
  5458.             m_pLWeapon->UpdateBob(m_fSwayHeight + m_fWeaponY, m_fSwayWidth);
  5459.             m_pLWeapon->Update(cdata.fPitch, cdata.fYaw, pos);
  5460.  
  5461.             pClientDE->GetObjectPos(pClientDE->GetClientObject(), &vPos);
  5462.             VEC_COPY(vGunMuzzlePos, m_pLWeapon->GetMuzzlePos());
  5463.             VEC_SUB(cdata.lGunMuzzlePos, vGunMuzzlePos, vPos);
  5464.         }
  5465.     }
  5466. }
  5467.  
  5468.  
  5469. // --------------------------------------------------------------------------- //
  5470. //
  5471. //    ROUTINE:    CBloodClientShell::ChangeWeapon()
  5472. //
  5473. //    PURPOSE:    Selects a new weapon
  5474. //
  5475. // --------------------------------------------------------------------------- //
  5476.  
  5477. void CBloodClientShell::ChangeWeapon(DBYTE slot)
  5478. {
  5479.     // Are we switching weapons?
  5480.     // If so, set our flags and get rid of the old one.
  5481.     if(slot != m_nCurGun) 
  5482.     {
  5483.         m_nCurGun = slot;
  5484.  
  5485.         if (m_pWeapon) 
  5486.         {
  5487.             delete m_pWeapon;
  5488.             m_pWeapon = DNULL;
  5489.         }
  5490.         if (m_pLWeapon) 
  5491.         {
  5492.             delete m_pLWeapon;
  5493.             m_pLWeapon = DNULL;
  5494.         }
  5495.  
  5496.         if (m_abyWeaponID[m_nCurGun])
  5497.         {
  5498.             m_pWeapon = CreateWeapon(m_abyWeaponID[m_nCurGun], DFALSE);
  5499.         }
  5500.         if (m_abyLWeaponID[m_nCurGun])
  5501.         {
  5502.             m_pLWeapon = CreateWeapon(m_abyLWeaponID[m_nCurGun], DTRUE);
  5503.         }
  5504.     }
  5505.  
  5506.     // Update the status bar stuff to reflect the new weapon
  5507.     m_NewStatusBar.UpdateCurrentWeap(m_nCurGun);
  5508.  
  5509.     if(m_pWeapon && (m_pWeapon->GetAmmoType(DTRUE) != m_pWeapon->GetAmmoType(DFALSE)))
  5510.         m_NewStatusBar.SetAltAmmo(m_dwAltAmmo);
  5511.     else
  5512.         m_NewStatusBar.SetAltAmmo(0);
  5513. }
  5514.  
  5515.  
  5516. // ----------------------------------------------------------------------- //
  5517. //
  5518. //    ROUTINE:    CBloodClientShell::SpecialEffectNotify()
  5519. //
  5520. //    PURPOSE:    Handle creation of a special fx
  5521. //
  5522. // ----------------------------------------------------------------------- //
  5523.  
  5524. void CBloodClientShell::SpecialEffectNotify(HLOCALOBJ hObj, HMESSAGEREAD hMessage)
  5525. {
  5526.     DDWORD dwClientFlags;
  5527.     CClientDE* pClientDE = GetClientDE();
  5528.     if(!pClientDE) return;
  5529.  
  5530.     if(hObj)
  5531.         pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE);
  5532.  
  5533.     DDWORD dwLocalID;
  5534.     pClientDE->GetLocalClientID(&dwLocalID);
  5535.  
  5536.     DBYTE nId = pClientDE->ReadFromMessageByte(hMessage);
  5537.  
  5538.     switch(nId)
  5539.     {
  5540.         case SFX_WEAPONHANDMODEL_ID:
  5541.         {
  5542.             DDWORD    cID = g_pClientDE->ReadFromMessageDWord(hMessage);
  5543.             DBYTE    byFlags = g_pClientDE->ReadFromMessageByte(hMessage);
  5544.             DBOOL    bLeft = byFlags >> 1;
  5545.             DBOOL    bVisible = byFlags & 0x01;
  5546.  
  5547.             if(cID != dwLocalID)
  5548.                 break;
  5549.  
  5550.             DDWORD dwFlags = pClientDE->GetObjectFlags(hObj);
  5551.  
  5552.             if (bVisible)
  5553.             {
  5554.                 pClientDE->SetObjectFlags(hObj, dwFlags | FLAG_VISIBLE);
  5555.                 pClientDE->SetObjectClientFlags(hObj, 0);
  5556.             }
  5557.             else
  5558.                 pClientDE->SetObjectFlags(hObj, dwFlags & ~FLAG_VISIBLE);
  5559.  
  5560.             if (bLeft)
  5561.                 m_hLWeapHandObj    = (bVisible) ? NULL : hObj;
  5562.             else
  5563.                 m_hWeapHandObj    = (bVisible) ? NULL : hObj;
  5564.  
  5565.             break;
  5566.         }
  5567.  
  5568.         case SFX_ORBCAM_ID:
  5569.         {
  5570.             DDWORD    cID = g_pClientDE->ReadFromMessageDWord(hMessage);
  5571.             DBYTE    bOn = g_pClientDE->ReadFromMessageByte(hMessage);
  5572.  
  5573.             if(cID != dwLocalID) break;
  5574.  
  5575.             if(m_hOrbObj == hObj)
  5576.             {
  5577.                 if(!bOn)
  5578.                 {
  5579.                     m_hOrbObj = DNULL;
  5580.                     break;
  5581.                 }
  5582.             }
  5583.             else
  5584.             {
  5585.                 if(bOn)
  5586.                     m_hOrbObj = hObj;
  5587.             }
  5588.  
  5589.             break;
  5590.         }
  5591.         
  5592.         case SFX_DESTRUCTABLEMODEL:
  5593.         {
  5594.             DVector vDims;
  5595.  
  5596.             dwClientFlags = pClientDE->GetObjectClientFlags( hObj );
  5597.             dwClientFlags |= CF_DONTSETDIMS;
  5598.             pClientDE->SetObjectClientFlags( hObj, dwClientFlags );
  5599.  
  5600.             pClientDE->ReadFromMessageCompVector( hMessage, &vDims );
  5601.  
  5602.             pClientDE->Physics( )->SetObjectDims( hObj, &vDims, 0 );
  5603.  
  5604.         }
  5605.         break;
  5606.  
  5607.         default:
  5608.             m_sfxMgr.HandleSFXMsg(hObj, hMessage, nId);
  5609.             break;
  5610.     }
  5611. }
  5612.  
  5613.  
  5614. // ----------------------------------------------------------------------- //
  5615. //
  5616. //    ROUTINE:    CBloodClientShell::OnObjectRemove()
  5617. //
  5618. //    PURPOSE:    Handle removal of a special fx
  5619. //
  5620. // ----------------------------------------------------------------------- //
  5621.  
  5622. void CBloodClientShell::OnObjectRemove(HLOCALOBJ hObj)
  5623. {
  5624.     CClientDE* pClientDE = GetClientDE();
  5625.     if (!pClientDE) return;
  5626.  
  5627.     if (!hObj) return;
  5628.  
  5629.     if (hObj == m_hWeapHandObj)
  5630.         m_hWeapHandObj = DNULL;
  5631.     else if (hObj == m_hLWeapHandObj)
  5632.         m_hLWeapHandObj = DNULL;
  5633.     else if (hObj == m_hSeeingEyeObj)
  5634.         m_hSeeingEyeObj = DNULL;
  5635.     else if (hObj == m_hOrbObj)
  5636.         m_hOrbObj = DNULL;
  5637.     else if (m_pCreature)
  5638.     {
  5639.         if(hObj == m_pCreature->m_hEnemyObject || hObj == m_pCreature->m_hServerObject)
  5640.             m_pCreature->Detach();
  5641.     }
  5642.     else
  5643.         m_sfxMgr.RemoveSpecialFX(hObj);
  5644. }
  5645.  
  5646.  
  5647. // --------------------------------------------------------------------------- //
  5648. //
  5649. //    ROUTINE:    CBloodClientShell::OnModelKey
  5650. //
  5651. //    PURPOSE:    Handle weapon model keys
  5652. //
  5653. // --------------------------------------------------------------------------- //
  5654.  
  5655. void CBloodClientShell::OnModelKey(HLOCALOBJ hObj, ArgList *pArgs)
  5656. {
  5657.     if (m_pWeapon && m_pWeapon->GetWeapObj() == hObj)
  5658.         m_pWeapon->OnModelKey(hObj, pArgs);
  5659.  
  5660.     if (m_pLWeapon && m_pLWeapon->GetWeapObj() == hObj)
  5661.         m_pLWeapon->OnModelKey(hObj, pArgs);
  5662. }
  5663.  
  5664.  
  5665. // ----------------------------------------------------------------------- //
  5666. //
  5667. //    ROUTINE:    CBloodClientShell::PauseGame()
  5668. //
  5669. //    PURPOSE:    Pauses/Unpauses the server
  5670. //
  5671. // ----------------------------------------------------------------------- //
  5672.  
  5673. void CBloodClientShell::PauseGame (DBOOL bPause)
  5674. {
  5675.     CClientDE* pClientDE = GetClientDE();
  5676.     if (!pClientDE) return;
  5677.  
  5678.     m_bRenderCamera = !bPause;
  5679.     m_bPaused = bPause;
  5680.  
  5681.     if (!IsMultiplayerGame())
  5682.     {
  5683.         HMESSAGEWRITE hWrite = pClientDE->StartMessage(CMSG_GAME_PAUSE);
  5684.         pClientDE->WriteToMessageByte(hWrite, (DBYTE)bPause);
  5685.         pClientDE->EndMessage(hWrite);
  5686.     }
  5687.  
  5688.     pClientDE->SetInputState(!bPause);
  5689.  
  5690.     if (bPause)
  5691.         pClientDE->PauseMusic();
  5692.     else
  5693.         pClientDE->ResumeMusic();
  5694. }
  5695.  
  5696.  
  5697. // --------------------------------------------------------------------------- //
  5698. //
  5699. //    ROUTINE:    CBloodClientShell::UpdateScreenShake
  5700. //
  5701. //    PURPOSE:    Update the screen shaking
  5702. //
  5703. // --------------------------------------------------------------------------- //
  5704.  
  5705. void CBloodClientShell::UpdateScreenShake()
  5706. {
  5707.     CClientDE* pClientDE = GetClientDE();
  5708.     if (!pClientDE || !m_hCamera) return;
  5709.  
  5710.     // Decay...
  5711.     DFLOAT fDecayAmount = 2.0f * pClientDE->GetFrameTime();
  5712.  
  5713.     m_vShakeMagnitude.x -= fDecayAmount;
  5714.     m_vShakeMagnitude.y -= fDecayAmount;
  5715.     m_vShakeMagnitude.z -= fDecayAmount;
  5716.  
  5717.     if (m_vShakeMagnitude.x < 0.0f) m_vShakeMagnitude.x = 0.0f;
  5718.     if (m_vShakeMagnitude.y < 0.0f) m_vShakeMagnitude.y = 0.0f;
  5719.     if (m_vShakeMagnitude.z < 0.0f) m_vShakeMagnitude.z = 0.0f;
  5720.  
  5721.  
  5722.     if (m_vShakeMagnitude.x <= 0.0f && m_vShakeMagnitude.y <= 0.0f && m_vShakeMagnitude.z <= 0.0f)
  5723.     {
  5724.         m_bShakeScreen = DFALSE;
  5725.         return;
  5726.     }
  5727.  
  5728.  
  5729.     // Apply...
  5730.  
  5731.     DFLOAT faddX = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.x * 3.0f;
  5732.     DFLOAT faddY = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.y * 3.0f;
  5733.     DFLOAT faddZ = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.z * 3.0f;
  5734.     m_fShakeCant = DEG2RAD(GetRandom(-0.5f, 0.5f) * m_vShakeMagnitude.x);
  5735.  
  5736.     DVector vPos, vAdd;
  5737.     VEC_SET(vAdd, faddX, faddY, faddZ);
  5738.  
  5739.     pClientDE->GetObjectPos(m_hCamera, &vPos);
  5740.     VEC_ADD(vPos, vPos, vAdd);
  5741.  
  5742.     pClientDE->SetObjectPos(m_hCamera, &vPos);
  5743.  
  5744.     // Shake the guns too..
  5745.     if (m_pWeapon && m_pWeapon->GetWeapObj())
  5746.     {
  5747.         pClientDE->GetObjectPos(m_pWeapon->GetWeapObj(), &vPos);
  5748.         VEC_MULSCALAR(vAdd, vAdd, 0.95f);
  5749.         VEC_ADD(vPos, vPos, vAdd);
  5750.         pClientDE->SetObjectPos(m_pWeapon->GetWeapObj(), &vPos);
  5751.     }
  5752.     if (m_pLWeapon && m_pLWeapon->GetWeapObj())
  5753.     {
  5754.         pClientDE->GetObjectPos(m_pLWeapon->GetWeapObj(), &vPos);
  5755.         VEC_MULSCALAR(vAdd, vAdd, 0.95f);
  5756.         VEC_ADD(vPos, vPos, vAdd);
  5757.         pClientDE->SetObjectPos(m_pLWeapon->GetWeapObj(), &vPos);
  5758.     }
  5759. }
  5760.  
  5761.  
  5762. // --------------------------------------------------------------------------- //
  5763. //
  5764. //    ROUTINE:    CBloodClientShell::UpdateScreenFlash
  5765. //
  5766. //    PURPOSE:    Update the screen Flash
  5767. //
  5768. // --------------------------------------------------------------------------- //
  5769.  
  5770. void CBloodClientShell::UpdateScreenFlash()
  5771. {
  5772.     CClientDE* pClientDE = GetClientDE();
  5773.     if (!pClientDE || !m_bFlashScreen) return;
  5774.  
  5775.     DVector vLightAdd;
  5776.     VEC_INIT(vLightAdd);
  5777.  
  5778.     DFLOAT fTime  = pClientDE->GetTime();
  5779.  
  5780.     // ramp up
  5781.     if ((m_fFlashRampUp > 0.0f) && (fTime < m_fFlashStart + m_fFlashRampUp))
  5782.     {
  5783.         DFLOAT fDelta = (fTime - m_fFlashStart);
  5784.         vLightAdd.x = fDelta * (m_vFlashColor.x) / m_fFlashRampUp;
  5785.         vLightAdd.y = fDelta * (m_vFlashColor.y) / m_fFlashRampUp;
  5786.         vLightAdd.z = fDelta * (m_vFlashColor.z) / m_fFlashRampUp;
  5787.     }
  5788.     // full tint
  5789.     else if (fTime < m_fFlashStart + m_fFlashRampUp + m_fFlashTime)
  5790.     {
  5791.         VEC_COPY(vLightAdd, m_vFlashColor);
  5792.     }
  5793.     // ramp down
  5794.     else if (VEC_MAGSQR(m_vFlashColor) > 0)
  5795.     {
  5796.         DVector vSub;
  5797.         DFLOAT fScale = pClientDE->GetFrameTime() * 2;
  5798.         VEC_SET(vSub, fScale, fScale, fScale);
  5799.         VEC_SUB(m_vFlashColor, m_vFlashColor, vSub);
  5800.         VEC_CLAMP(m_vFlashColor, 0, 2.0f);
  5801.  
  5802.         VEC_COPY(vLightAdd, m_vFlashColor);
  5803.  
  5804.         // Add it to any additional camera light we're adding..
  5805.     }
  5806.     else
  5807.     {
  5808.         m_bFlashScreen = DFALSE;
  5809.     }
  5810.  
  5811.     VEC_CLAMP(vLightAdd, 0, 1.0f);
  5812.  
  5813.     VEC_ADD(m_vCameraAdd, m_vCameraAdd, vLightAdd);
  5814. }
  5815.  
  5816.  
  5817. // --------------------------------------------------------------------------- //
  5818. //
  5819. //    ROUTINE:    CBloodClientShell::UpdateContainerFX
  5820. //
  5821. //    PURPOSE:    Update any client side container fx
  5822. //
  5823. // --------------------------------------------------------------------------- //
  5824.  
  5825. void CBloodClientShell::UpdateContainerFX()
  5826. {
  5827.     CClientDE* pClientDE = GetClientDE();
  5828.     if (!pClientDE || !m_hCamera) return;
  5829.  
  5830.     DVector vPos;
  5831.     pClientDE->GetObjectPos(m_hCamera, &vPos);
  5832.  
  5833.     HLOCALOBJ objList[1];
  5834.     DDWORD dwNum = pClientDE->GetPointContainers(&vPos, objList, 1);
  5835.  
  5836.     char* pCurSound        = DNULL;
  5837.     DBOOL bUpdateScale    = DFALSE;
  5838.     ContainerCode eCode = CC_NOTHING;
  5839.     DDWORD dwUserFlags    = FLAG_VISIBLE;
  5840.     DBOOL bUseWorldFog    = DTRUE;
  5841.  
  5842.     // Get the user flags associated with the container, and make sure that
  5843.     // the container isn't hidden...
  5844.  
  5845.     if (dwNum > 0 && objList[0])
  5846.     {
  5847.         pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags);
  5848.     }
  5849.  
  5850.  
  5851.     if (dwNum > 0 && (dwUserFlags & FLAG_VISIBLE))
  5852.     {
  5853.         D_WORD code;
  5854.         if (pClientDE->GetContainerCode(objList[0], &code))
  5855.         {
  5856.             eCode = (ContainerCode)code;
  5857.  
  5858.             // See if we have entered/left a container...
  5859.  
  5860.             DFLOAT fTime = pClientDE->GetTime();
  5861.  
  5862.             if (m_eCurContainerCode != eCode)
  5863.             {
  5864.                 m_fContainerStartTime = fTime;
  5865.  
  5866.                 // See if this container has fog associated with it..
  5867.  
  5868.                 CVolumeBrushFX* pFX = (CVolumeBrushFX*)m_sfxMgr.FindStaticSpecialFX(objList[0]);
  5869.                 if (pFX)
  5870.                 {
  5871.                     bUseWorldFog = DFALSE;
  5872.                     DBOOL bFog     = pFX->IsFogEnable();
  5873.  
  5874.                     char buf[30];
  5875.                     sprintf(buf, "FogEnable %d", (int)bFog);
  5876.                     pClientDE->RunConsoleString(buf);
  5877.  
  5878.                     if (bFog)
  5879.                     {
  5880.                         sprintf(buf, "FogNearZ %d", (int)pFX->GetFogNearZ());
  5881.                         pClientDE->RunConsoleString(buf);
  5882.  
  5883.                         sprintf(buf, "FogFarZ %d", (int)pFX->GetFogFarZ());
  5884.                         pClientDE->RunConsoleString(buf);
  5885.  
  5886.                         DVector vFogColor = pFX->GetFogColor();
  5887.  
  5888.                         sprintf(buf, "FogR %d", (int)vFogColor.x);
  5889.                         pClientDE->RunConsoleString(buf);
  5890.  
  5891.                         sprintf(buf, "FogG %d", (int)vFogColor.y);
  5892.                         pClientDE->RunConsoleString(buf);
  5893.  
  5894.                         sprintf(buf, "FogB %d", (int)vFogColor.z);
  5895.                         pClientDE->RunConsoleString(buf);
  5896.                     }
  5897.                 }                
  5898.             }
  5899.  
  5900.             char *pWaterSound = "Sounds\\Player\\Underwaterloop1.wav";
  5901.             switch (eCode)
  5902.             {
  5903.                 case CC_WATER:
  5904.                 {
  5905.                     VEC_SET(m_vLightScale, 0.3f, 0.8f, 0.8f);
  5906.                     pCurSound = pWaterSound;
  5907.                 }
  5908.                 break;
  5909.  
  5910.                 case CC_BLOOD:
  5911.                 {
  5912.                     VEC_SET(m_vLightScale, 1.0f, 0.0f, 0.0f);
  5913.                     pCurSound = pWaterSound;
  5914.                 }
  5915.                 break;
  5916.                 
  5917.                 case CC_ACID:
  5918.                 {
  5919.                     VEC_SET(m_vLightScale, 0.0f, 0.8f, 0.4f);
  5920.                     pCurSound = pWaterSound;
  5921.                 }
  5922.                 break;
  5923.  
  5924.                 case CC_FREEFALL:
  5925.                 {
  5926.                     DFLOAT fFallTime = 1.5f;
  5927.                     DFLOAT fScale = 0.0f;
  5928.  
  5929.                     if (fTime < m_fContainerStartTime + fFallTime)
  5930.                     {
  5931.                         DFLOAT fTimeLeft = (m_fContainerStartTime + fFallTime) - fTime;
  5932.                         fScale = fTimeLeft/fFallTime;
  5933.                     }
  5934.                     VEC_SET(m_vLightScale, fScale, fScale, fScale);
  5935.                 }
  5936.                 break;
  5937.  
  5938.                 default : break;
  5939.             }
  5940.  
  5941.         }
  5942.     }
  5943.  
  5944.  
  5945.     // See if we have entered/left a container...
  5946.  
  5947.     if (m_eCurContainerCode != eCode || bUpdateScale)
  5948.     {
  5949.         // Adjust Fog as necessary...
  5950.         
  5951.         if (bUseWorldFog)
  5952.         {
  5953.             ResetGlobalFog();
  5954.         }
  5955.  
  5956.         // See if we are coming out of water...
  5957.  
  5958.         if (IsLiquid(m_eCurContainerCode) && !IsLiquid(eCode))
  5959.         {
  5960.             UpdateUnderWaterFX(DFALSE);
  5961.         }
  5962.  
  5963.         m_eCurContainerCode = eCode;
  5964.  
  5965.         if (m_hContainerSound)
  5966.         {
  5967.             pClientDE->KillSound(m_hContainerSound);
  5968.             m_hContainerSound = DNULL;
  5969.         }
  5970.  
  5971.         if (pCurSound)
  5972.         {
  5973.             PlaySoundInfo playSoundInfo;
  5974.             PLAYSOUNDINFO_INIT(playSoundInfo);
  5975.  
  5976.             playSoundInfo.m_dwFlags = PLAYSOUND_CLIENT | PLAYSOUND_LOCAL | PLAYSOUND_LOOP | PLAYSOUND_GETHANDLE;
  5977.             _mbscpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)pCurSound);
  5978.             playSoundInfo.m_nVolume = 20;
  5979.             if( pClientDE->PlaySound(&playSoundInfo) == LT_OK )
  5980.                 m_hContainerSound = playSoundInfo.m_hSound;
  5981.         }
  5982.  
  5983. //        pClientDE->SetCameraLightAdd(m_hCamera, &vLightAdd);
  5984.     }
  5985.  
  5986.  
  5987.     // See if we are under water (under any liquid)...
  5988.  
  5989.     if (IsLiquid(m_eCurContainerCode)) 
  5990.     {
  5991.         UpdateUnderWaterFX();
  5992.     }
  5993. }
  5994.  
  5995.  
  5996. // --------------------------------------------------------------------------- //
  5997. //
  5998. //    ROUTINE:    CBloodClientShell::UpdateUnderWaterFX
  5999. //
  6000. //    PURPOSE:    Update under water fx
  6001. //
  6002. // --------------------------------------------------------------------------- //
  6003.  
  6004. void CBloodClientShell::UpdateUnderWaterFX(DBOOL bUpdate)
  6005. {
  6006.     CClientDE* pClientDE = GetClientDE();
  6007.     if (!pClientDE || !m_hCamera || m_bZoomView) return;
  6008.  
  6009. //    DDWORD dwWidth = 640, dwHeight = 480;
  6010. //    pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &dwWidth, &dwHeight);
  6011.  
  6012.     if (m_dwScreenWidth < 0 || m_dwScreenHeight < 0) return;
  6013.  
  6014.     // Initialize to default fov x and y...
  6015.  
  6016.     DFLOAT fFovX = m_fovX;
  6017.     DFLOAT fFovY = fFovX * m_fovYScale;
  6018.     
  6019.     if (bUpdate)
  6020.     {
  6021.         pClientDE->GetCameraFOV(m_hCamera, &fFovX, &fFovY);
  6022.  
  6023.         DFLOAT fSpeed = .02f * pClientDE->GetFrameTime();
  6024.  
  6025.         if (m_fFovXFXDir > 0)
  6026.         {
  6027.             fFovY += fSpeed;
  6028.             fFovX -= fSpeed;
  6029.  
  6030.             if (fFovY > m_fovX * m_fovYScale)
  6031.             {
  6032.                 fFovY = m_fovX * m_fovYScale;
  6033.                 m_fFovXFXDir = -m_fFovXFXDir;
  6034.             }
  6035.         }
  6036.         else
  6037.         {
  6038.             fFovY -= fSpeed;
  6039.             fFovX += fSpeed;
  6040.  
  6041.             if (fFovY < (m_fovX * m_dwScreenHeight - 40) / m_dwScreenWidth)
  6042.             {
  6043.                 fFovY = (m_fovX * m_dwScreenHeight - 40) / m_dwScreenWidth;
  6044.                 m_fFovXFXDir = -m_fFovXFXDir;
  6045.             }
  6046.         }
  6047.     }
  6048.  
  6049.     pClientDE->SetCameraFOV(m_hCamera, fFovX, fFovY);
  6050. }
  6051.  
  6052. // --------------------------------------------------------------------------- //
  6053. //
  6054. //    ROUTINE:    CBloodClientShell::UpdateWonkyVision
  6055. //
  6056. //    PURPOSE:    Update WonkyVision (baddest LCD trip in da mofo)
  6057. //
  6058. // --------------------------------------------------------------------------- //
  6059.  
  6060. void CBloodClientShell::UpdateWonkyVision(DBOOL bUpdate)
  6061. {
  6062.     CClientDE* pClientDE = GetClientDE();
  6063.     if (!pClientDE || !m_hCamera || m_bZoomView) return;
  6064.  
  6065.     if (m_dwScreenWidth < 0 || m_dwScreenHeight < 0) return;
  6066.  
  6067.     DFLOAT fovX = m_fovX;
  6068.     DFLOAT fovY = m_fovY;
  6069.  
  6070.     DVector vU, vF, vR;
  6071.     pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &vF);
  6072.  
  6073.     pClientDE->RunConsoleString("ModelWarble 1");
  6074.     pClientDE->RunConsoleString("WarbleSpeed 15");
  6075.     pClientDE->RunConsoleString("WarbleScale .90");
  6076.  
  6077.     DFLOAT fSpeed = 0.2f * pClientDE->GetFrameTime();
  6078.     fSpeed = DCLAMP( fSpeed, 0.0f, 0.010f );
  6079.  
  6080.     // FOV
  6081.     if (m_fFovXFXDir > 0)
  6082.     {
  6083.         m_fOffsetY += fSpeed;
  6084.         m_fOffsetX -= fSpeed;
  6085.  
  6086.         fovY += m_fOffsetY;
  6087.         fovX += m_fOffsetX;
  6088.  
  6089.         if (fovY > fovX * m_fovYScale)
  6090.         {
  6091.             fovY = fovX * m_fovYScale;
  6092.             m_fFovXFXDir = -m_fFovXFXDir;
  6093.         }
  6094.     }
  6095.     else
  6096.     {
  6097.         m_fOffsetY -= fSpeed;
  6098.         m_fOffsetX += fSpeed;
  6099.  
  6100.         fovY += m_fOffsetY;
  6101.         fovX += m_fOffsetX;
  6102.  
  6103.         if (fovY < (fovX * m_dwScreenHeight - 120) / m_dwScreenWidth)
  6104.         {
  6105.             fovY = (fovX * m_dwScreenHeight - 120) / m_dwScreenWidth;
  6106.             m_fFovXFXDir = -m_fFovXFXDir;
  6107.         }
  6108.     }
  6109.  
  6110.     // ROTATION
  6111.     if(m_fRotDir > 0)
  6112.     {
  6113.         m_fOffsetRot += fSpeed * 1.5f;
  6114.  
  6115.         if(m_fOffsetRot >= m_fMaxRot)
  6116.         {
  6117.             m_fRotDir = -m_fRotDir;
  6118.             m_fMaxRot = -0.55f * GetRandom(1.0f, 2.0f);
  6119.         }
  6120.     }
  6121.     else
  6122.     {
  6123.         m_fOffsetRot -= fSpeed * 1.5f;
  6124.  
  6125.         if(m_fOffsetRot <= m_fMaxRot)
  6126.         {
  6127.             m_fRotDir = -m_fRotDir;
  6128.             m_fMaxRot = 0.55f * GetRandom(1.0f, 2.0f);
  6129.         }
  6130.     }
  6131.  
  6132.     if (fovX < 1.3f) fovX = 1.3f;
  6133.     if (fovX > 1.8f) fovX = 1.8f;
  6134.  
  6135.     if (fovY < 1.0f) fovY = 1.0f;
  6136.     if (fovY > 1.3f) fovY = 1.3f;
  6137.  
  6138.     pClientDE->SetCameraFOV(m_hCamera, fovX, fovY);
  6139.     pClientDE->RotateAroundAxis(&m_Rotation, &vF, m_fOffsetRot);
  6140.     pClientDE->SetObjectRotation(m_hCamera, &m_Rotation);
  6141.  
  6142.     return;
  6143. }
  6144.  
  6145. // ----------------------------------------------------------------------- //
  6146. //
  6147. //    ROUTINE:    CBloodClientShell::ShakeScreen()
  6148. //
  6149. //    PURPOSE:    Shake screen
  6150. //
  6151. // ----------------------------------------------------------------------- //
  6152.  
  6153. void CBloodClientShell::ShakeScreen(DVector *vShake, DFLOAT fTime)
  6154. {
  6155.     CClientDE* pClientDE = GetClientDE();
  6156.     if (!pClientDE) return;
  6157.  
  6158.     m_fShakeStart        = GetClientDE()->GetTime();
  6159.     m_fShakeTime        = fTime;
  6160.  
  6161.     VEC_ADD(m_vShakeMagnitude, m_vShakeMagnitude, *vShake);
  6162.  
  6163.     if (m_vShakeMagnitude.x > 3.5f) m_vShakeMagnitude.x = 3.5f;
  6164.     if (m_vShakeMagnitude.y > 3.5f) m_vShakeMagnitude.y = 3.5f;
  6165.     if (m_vShakeMagnitude.z > 3.5f) m_vShakeMagnitude.z = 3.5f;
  6166.  
  6167.     m_bShakeScreen = DTRUE;
  6168. }
  6169.  
  6170.  
  6171. // ----------------------------------------------------------------------- //
  6172. //
  6173. //    ROUTINE:    CBloodClientShell::FlashScreen()
  6174. //
  6175. //    PURPOSE:    Flash screen
  6176. //
  6177. // ----------------------------------------------------------------------- //
  6178.  
  6179. void CBloodClientShell::FlashScreen(DVector *vFlashColor, DFLOAT fTime, DFLOAT fRampUp)
  6180. {
  6181.     if (!GetClientDE()) return;
  6182.  
  6183.     m_fFlashStart        = GetClientDE()->GetTime();
  6184.     m_fFlashTime        = fTime;
  6185.  
  6186.     m_vFlashColor.x += vFlashColor->x;
  6187.     m_vFlashColor.y += vFlashColor->y;
  6188.     m_vFlashColor.z += vFlashColor->z;
  6189.  
  6190.     // Scale lowest value to max of 1.0 (so we don't oversaturate)
  6191.     DFLOAT fMin = m_vFlashColor.x;
  6192.     fMin = (m_vFlashColor.y < fMin) ? m_vFlashColor.y : fMin;
  6193.     fMin = (m_vFlashColor.z < fMin) ? m_vFlashColor.z : fMin;
  6194.  
  6195.     if (fMin > 1.0f)
  6196.     {
  6197.         fMin = 1.0f/fMin;
  6198.         m_vFlashColor.x *= fMin;
  6199.         m_vFlashColor.y *= fMin;
  6200.         m_vFlashColor.z *= fMin;
  6201.     }
  6202.  
  6203.  
  6204.     // if screen is already flashing, don't ramp up..
  6205.     if (!m_bFlashScreen)
  6206.         m_fFlashRampUp    = fRampUp;
  6207.     else
  6208.         m_fFlashRampUp = 0.0f;
  6209.  
  6210.     m_bFlashScreen    = DTRUE;
  6211. }
  6212.  
  6213.  
  6214. // ----------------------------------------------------------------------- //
  6215. //
  6216. //    ROUTINE:    CBloodClientShell::HandleExitWorld()
  6217. //
  6218. //    PURPOSE:    The player has hit an exit trigger.
  6219. //
  6220. // ----------------------------------------------------------------------- //
  6221.  
  6222. void CBloodClientShell::HandleExitWorld(HMESSAGEREAD hMessage)
  6223. {
  6224.     CClientDE* pClientDE = GetClientDE();
  6225.     if (!pClientDE) return;
  6226.  
  6227.     // don't go to the next level if you are dead
  6228.     if (m_bDead)
  6229.         return;
  6230.  
  6231.     // Stop the music
  6232.     m_Music.TermPlayLists();
  6233.     pClientDE->StopMusic (MUSIC_IMMEDIATE);    // Stop the music
  6234.     m_eMusicLevel = CMusic::MUSICLEVEL_SILENCE;
  6235.  
  6236.     // kill the sounds
  6237.     if (m_hContainerSound)
  6238.     {
  6239.         pClientDE->KillSound(m_hContainerSound);
  6240.         m_hContainerSound = DNULL;
  6241.     }
  6242.  
  6243.     if( m_hNightGogglesSound )
  6244.     {
  6245.         g_pClientDE->KillSound( m_hNightGogglesSound );
  6246.     }
  6247.  
  6248.     if( m_hTheEyeLoopingSound )
  6249.     {
  6250.         g_pClientDE->KillSound( m_hTheEyeLoopingSound );
  6251.     }
  6252.  
  6253.  
  6254.     // Get the new world
  6255.     HSTRING hstrNextWorld = pClientDE->ReadFromMessageHString(hMessage);
  6256.     m_nLastExitType = pClientDE->ReadFromMessageByte(hMessage);
  6257.  
  6258.     if (!hstrNextWorld)
  6259.     {
  6260.         PrintError("Invalid data in CBloodClientShell::HandleExitWorld()!");
  6261.         return;
  6262.     }
  6263.  
  6264. #ifdef _DEMO
  6265.     if (_mbsicmp((const unsigned char*)"EndGame", (const unsigned char*)pClientDE->GetStringData(hstrNextWorld)) == 0)
  6266.     {
  6267.         m_bInWorld = DFALSE;
  6268.         PauseGame(DTRUE);
  6269.         m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  6270.         PlaySoundLocal("sounds\\interface\\mainmenus\\enter01.wav", SOUNDPRIORITY_MISC_HIGH, DFALSE, DFALSE, DFALSE, DFALSE, 100);
  6271.         Splash_SetState(pClientDE, "\\screens\\info.pcx");
  6272.         return;
  6273.     }
  6274. #endif
  6275.  
  6276.     _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)pClientDE->GetStringData(hstrNextWorld));
  6277.     StartNewWorld(m_szFilename, m_nGameType, LOADTYPE_NEW_LEVEL);
  6278.     pClientDE->FreeString(hstrNextWorld);
  6279.     m_bFirstWorld = DFALSE;
  6280. }
  6281.  
  6282.  
  6283. // ----------------------------------------------------------------------- //
  6284. //
  6285. //    ROUTINE:    CBloodClientShell::StartNewWorld()
  6286. //
  6287. //    PURPOSE:    Start the new world
  6288. //
  6289. // ----------------------------------------------------------------------- //
  6290.  
  6291. DBOOL CBloodClientShell::StartNewWorld(char *pszWorld, DBYTE nGameType, DBYTE nLoadType, DBYTE nDifficulty)
  6292. {
  6293.     CClientDE* pClientDE = GetClientDE();
  6294.     if (!pClientDE) return DFALSE;
  6295.  
  6296.     if (pszWorld)
  6297.     {
  6298.         // Set up the world title string
  6299.         if (m_hstrTitle) { pClientDE->FreeString(m_hstrTitle); m_hstrTitle = 0; }
  6300.         if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; }
  6301.         if (m_nLoadScreenID) m_nLoadScreenID = 0;
  6302.  
  6303.         GetWorldTitle(pszWorld);
  6304.  
  6305.         if(m_nLoadScreenID)        PauseGame(DTRUE);
  6306.             else                PauseGame(DFALSE);
  6307.  
  6308.         // Clear the current objective...
  6309.         m_NewStatusBar.InitObjectivesTab();
  6310.  
  6311.         // Send a message to the server to load a new world
  6312.         HMESSAGEWRITE hMsg;
  6313.         hMsg = pClientDE->StartMessage(CMSG_LOADWORLD);
  6314.         pClientDE->WriteToMessageString(hMsg, pszWorld);        // Filename
  6315.         pClientDE->WriteToMessageByte(hMsg, nGameType);            // Game type
  6316.         pClientDE->WriteToMessageByte(hMsg, nLoadType);            // Load type
  6317.         pClientDE->WriteToMessageByte(hMsg, nDifficulty);        // Difficulty level
  6318.         pClientDE->EndMessage(hMsg);
  6319.  
  6320.         SetGameState(GS_LOADINGLEVEL);
  6321.  
  6322.         m_nGameType = nGameType;
  6323.         m_nLastLoadType = nLoadType;
  6324.  
  6325.         m_bInWorld = DFALSE;
  6326.  
  6327.         m_bZoomView = DFALSE;
  6328.         m_bShowCrosshair = m_bCrosshairOriginallyOn;
  6329.         m_nCrosshair = m_nCrosshairOriginalNum;
  6330.  
  6331.         m_bBlind = DFALSE;
  6332.         m_nTrapped = 0;
  6333.     }
  6334.     else
  6335.     {
  6336.         PrintError("Error invalid world!");
  6337.         return DFALSE;
  6338.     }
  6339.  
  6340.     return DTRUE;
  6341. }
  6342.  
  6343. // ----------------------------------------------------------------------- //
  6344. //
  6345. //    ROUTINE:    CBloodClientShell::SaveClientData
  6346. //
  6347. //    PURPOSE:    Send client save data to server so it can be put into save file.
  6348. //
  6349. // ----------------------------------------------------------------------- //
  6350.  
  6351. void CBloodClientShell::SaveClientData( HMESSAGEWRITE hMsg )
  6352. {
  6353.     HMESSAGEWRITE hSaveMsg;
  6354.  
  6355.     hSaveMsg = g_pClientDE->StartHMessageWrite( );
  6356.  
  6357.     m_eMusicLevel = m_Music.GetMusicLevel();
  6358.  
  6359.     // Start save data...
  6360.  
  6361.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bNightGogglesActive );
  6362.     g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fWonkyTime );
  6363.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bWonkyVision );
  6364.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bWonkyNoMove );
  6365.     g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fBlindTime );
  6366.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bBlind );
  6367.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bFadeIn );
  6368.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_bFadeOut );
  6369.     g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fFadeVal );
  6370. //    g_pClientDE->WriteToMessageByte( hSaveMsg, m_nCrosshair );
  6371.     g_pClientDE->WriteToMessageByte( hSaveMsg, m_eMusicLevel );
  6372.     g_pClientDE->WriteToMessageFloat( hSaveMsg, (float)m_nLastLoadType );
  6373.     g_pClientDE->WriteToMessageFloat( hSaveMsg, (float)m_nGameType );
  6374.     g_pClientDE->WriteToMessageHString( hSaveMsg, m_hstrObjectivesTitle );
  6375.     g_pClientDE->WriteToMessageHString( hSaveMsg, m_hstrObjectivesText );
  6376.  
  6377.     // End save data...
  6378.  
  6379.     g_pClientDE->WriteToMessageHMessageWrite( hMsg, hSaveMsg );
  6380.     g_pClientDE->EndHMessageWrite( hSaveMsg );
  6381. }
  6382.  
  6383. // ----------------------------------------------------------------------- //
  6384. //
  6385. //    ROUTINE:    CBloodClientShell::LoadClientData
  6386. //
  6387. //    PURPOSE:    Send client save data to server so it can be put into save file.
  6388. //
  6389. // ----------------------------------------------------------------------- //
  6390.  
  6391. void CBloodClientShell::LoadClientData( HMESSAGEREAD hMsg )
  6392. {
  6393.     HMESSAGEREAD hLoadMsg;
  6394.     DBOOL bNightVisionActive;
  6395.  
  6396.     if (m_hstrObjectivesTitle)
  6397.     {
  6398.         g_pClientDE->FreeString(m_hstrObjectivesTitle);
  6399.         m_hstrObjectivesTitle = DNULL;
  6400.     }
  6401.     if (m_hstrObjectivesText)
  6402.     {
  6403.         g_pClientDE->FreeString(m_hstrObjectivesText);
  6404.         m_hstrObjectivesText = DNULL;
  6405.     }
  6406.  
  6407.     hLoadMsg = g_pClientDE->ReadFromMessageHMessageRead( hMsg );
  6408.     
  6409.     bNightVisionActive = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6410.     m_fWonkyTime    = g_pClientDE->ReadFromMessageFloat( hLoadMsg );
  6411.     m_bWonkyVision    = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6412.     m_bWonkyNoMove    = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6413.     m_fBlindTime    = g_pClientDE->ReadFromMessageFloat( hLoadMsg );
  6414.     m_bBlind        = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6415.     m_bFadeIn        = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6416.     m_bFadeOut        = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6417.     m_fFadeVal        = g_pClientDE->ReadFromMessageFloat( hLoadMsg );
  6418. //    m_nCrosshair    = g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6419.     m_eMusicLevel    = (CMusic::EMusicLevel) g_pClientDE->ReadFromMessageByte( hLoadMsg );
  6420.     int nTmp        = (int)g_pClientDE->ReadFromMessageFloat( hLoadMsg );
  6421.     m_nGameType        = (int)g_pClientDE->ReadFromMessageFloat( hLoadMsg );
  6422.     m_hstrObjectivesTitle = g_pClientDE->ReadFromMessageHString( hLoadMsg );
  6423.     m_hstrObjectivesText = g_pClientDE->ReadFromMessageHString( hLoadMsg );
  6424.  
  6425.     if (m_hstrObjectivesTitle && m_hstrObjectivesText)
  6426.         m_NewStatusBar.UpdateObjectives(g_pClientDE->GetStringData(m_hstrObjectivesTitle), g_pClientDE->GetStringData(m_hstrObjectivesText));
  6427.  
  6428.     g_pClientDE->EndHMessageRead( hLoadMsg );
  6429.  
  6430.     g_pClientDE->RunConsoleString("maxfps 0");
  6431. }
  6432.  
  6433. // --------------------------------------------------------------------------- //
  6434. //
  6435. //    ROUTINE:    CBloodClientShell::ShowPlayer()
  6436. //
  6437. //    PURPOSE:    Show or hide the player object
  6438. //
  6439. // --------------------------------------------------------------------------- //
  6440.  
  6441. HLOCALOBJ m_hLastWeapHandObj = DNULL;
  6442. HLOCALOBJ m_hLastLWeapHandObj = DNULL;
  6443.  
  6444. void CBloodClientShell::ShowPlayer(DBOOL bShow)
  6445. {
  6446.     CClientDE* pClientDE = GetClientDE();
  6447.     if (!pClientDE) return;
  6448.  
  6449.     HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  6450.     if (!hPlayerObj) return;
  6451.  
  6452.     DDWORD dwFlags = pClientDE->GetObjectFlags(hPlayerObj);
  6453.     if (bShow)
  6454.     {
  6455.         dwFlags |= FLAG_VISIBLE;
  6456.         cdata.byFlags &= ~CDATA_SHOWGUN;
  6457.     }
  6458.     else
  6459.     {
  6460.         dwFlags &= ~FLAG_VISIBLE;
  6461.         cdata.byFlags |= CDATA_SHOWGUN;
  6462.     }
  6463.     pClientDE->SetObjectFlags(hPlayerObj, dwFlags);
  6464.  
  6465.     if((m_hLastWeapHandObj != m_hWeapHandObj) || (m_hLastLWeapHandObj != m_hLWeapHandObj))
  6466.     {
  6467.         m_hLastWeapHandObj = m_hWeapHandObj;
  6468.         m_hLastLWeapHandObj = m_hLWeapHandObj;
  6469.     }
  6470.  
  6471.     if (m_hWeapHandObj)
  6472.     {
  6473.         DDWORD dwFlags = pClientDE->GetObjectFlags(m_hWeapHandObj);
  6474.  
  6475.         if(bShow)    dwFlags |= FLAG_VISIBLE;
  6476.             else    dwFlags &= ~FLAG_VISIBLE;
  6477.  
  6478.         pClientDE->SetObjectFlags(m_hWeapHandObj, dwFlags);
  6479.     }
  6480.  
  6481.     if (m_hLWeapHandObj)
  6482.     {
  6483.         DDWORD dwFlags = pClientDE->GetObjectFlags(m_hLWeapHandObj);
  6484.  
  6485.         if (bShow)    dwFlags |= FLAG_VISIBLE;
  6486.             else    dwFlags &= ~FLAG_VISIBLE;
  6487.  
  6488.         pClientDE->SetObjectFlags(m_hLWeapHandObj, dwFlags);
  6489.     }
  6490. }
  6491.  
  6492.  
  6493.  
  6494. // ----------------------------------------------------------------------- //
  6495. //
  6496. //    ROUTINE:    CBloodClientShell::DrawLoadingScreen()
  6497. //
  6498. //    PURPOSE:    Update the loading screen
  6499. //
  6500. // ----------------------------------------------------------------------- //
  6501.  
  6502. void CBloodClientShell::DrawLoadingScreen()
  6503. {
  6504.     CClientDE* pClientDE = GetClientDE();
  6505.     if (!pClientDE) return;
  6506.  
  6507.     HSURFACE hScreen = pClientDE->GetScreenSurface();
  6508.     if (!hScreen) return;
  6509.  
  6510.     HSURFACE hTemp = DNULL;
  6511.     DDWORD     screenWidth, screenHeight;
  6512.  
  6513.     pClientDE->GetSurfaceDims(hScreen, &screenWidth, &screenHeight);
  6514.  
  6515.     // If we don't have a loading screen, create one
  6516.     if(!m_hLoadingScreen)
  6517.     {
  6518.         // Create the loading screen surface the same size as the screen
  6519.         m_hLoadingScreen = pClientDE->CreateSurface(screenWidth, screenHeight);
  6520.  
  6521.         if(m_hstrLoadScreen)
  6522.             hTemp = pClientDE->CreateSurfaceFromBitmap(pClientDE->GetStringData(m_hstrLoadScreen));
  6523.         else
  6524.         {
  6525.             hTemp = pClientDE->CreateSurfaceFromBitmap("Interface\\LoadScreens\\LoadScreen.pcx");
  6526.             pClientDE->DrawBitmapToSurface(hTemp, "Interface\\LoadScreens\\LoadingText\\Loading_01.pcx", DNULL, 215, 321);
  6527.         }
  6528.  
  6529.         // Scale the bitmap to the loading screen and dump the temp surface
  6530.         pClientDE->ScaleSurfaceToSurface(m_hLoadingScreen, hTemp, DNULL, DNULL);
  6531.         pClientDE->DeleteSurface(hTemp);
  6532.         hTemp = DNULL;
  6533.     }
  6534.  
  6535.     // Init the fonts and cursor
  6536.     CoolFontCursor    *m_hLoadCursor = 0;
  6537.     CoolFont        *m_hLoadTitleFont = 0;
  6538.     CoolFont        *m_hLoadTextFont = 0;
  6539.  
  6540.     m_hLoadCursor = new CoolFontCursor();
  6541.     m_hLoadTitleFont = new CoolFont();
  6542.     m_hLoadTextFont = new CoolFont();
  6543.  
  6544.     m_hLoadTitleFont->Init(pClientDE, "interface/statusbar/fonts/stat_font_1.pcx");
  6545.     m_hLoadTitleFont->LoadXWidths("interface/statusbar/fonts/stat_font_1.fnt");
  6546.  
  6547.     m_hLoadTextFont->Init(pClientDE, "interface/objectives/obj_font_1.pcx");
  6548.     m_hLoadTextFont->LoadXWidths("interface/objectives/obj_font_1.fnt");
  6549.  
  6550. #ifdef _DEMO
  6551.  
  6552.     // Draw the title of the level
  6553.     m_hLoadCursor->SetFont(m_hLoadTitleFont);
  6554.     m_hLoadCursor->SetDest(m_hLoadingScreen);
  6555.     m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER);
  6556.     m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(m_hLoadTitleFont->height * 2));
  6557.  
  6558.     if(m_hstrTitle)
  6559.     {
  6560.         m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle));
  6561.         m_hLoadCursor->NewLine();
  6562.     }
  6563.  
  6564. #else
  6565.  
  6566.     if(!m_nLoadScreenID)
  6567.     {
  6568.         // Draw the title of the level
  6569.         m_hLoadCursor->SetFont(m_hLoadTitleFont);
  6570.         m_hLoadCursor->SetDest(m_hLoadingScreen);
  6571.         m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER);
  6572.         m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(m_hLoadTitleFont->height * 2));
  6573.  
  6574.         if(m_hstrTitle)
  6575.         {
  6576.             m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle));
  6577.             m_hLoadCursor->NewLine();
  6578.         }
  6579.  
  6580.         // Draw the loading screen...
  6581.         pClientDE->DrawSurfaceToSurface(hScreen, m_hLoadingScreen, DNULL, 0, 0);
  6582.     }
  6583.     else
  6584.     {
  6585.         HSTRING            hStr;
  6586.         LoadScreenData    *lsd = &(g_LoadScreenData[m_nLoadScreenID]);
  6587.         DFLOAT            ratioX = (float)screenWidth / 640.0f;
  6588.         DFLOAT            ratioY = (float)screenHeight / 480.0f;
  6589.         short            newX, newY;
  6590.  
  6591.         m_hLoadCursor->SetFont(m_hLoadTitleFont);
  6592.         m_hLoadCursor->SetDest(m_hLoadingScreen);
  6593.         m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER);
  6594.  
  6595.         // Find the scaled location for the title and draw it center justified
  6596.         newX = (short)(lsd->nTitleX * ratioX);
  6597.         newY = (short)(lsd->nTitleY * ratioY);
  6598.  
  6599.         // Draw the title of the level
  6600.         m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 2));
  6601.  
  6602.         if(m_hstrTitle)
  6603.             m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle));
  6604.  
  6605.         m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 3));
  6606.         hStr = pClientDE->FormatString(lsd->nTitle);
  6607.         m_hLoadCursor->Draw(pClientDE->GetStringData(hStr));
  6608.         pClientDE->FreeString(hStr);
  6609.  
  6610.         if(m_nGameType != GAMETYPE_ACTION && screenWidth >= 512 && screenHeight >= 384)
  6611.         {
  6612.             // Find the scaled location for the text and draw it in formatted mode
  6613.             newX = (short)(lsd->nTextX * ratioX);
  6614.             newY = (short)(lsd->nTextY * ratioY);
  6615.  
  6616.             m_hLoadCursor->SetFont(m_hLoadTextFont);
  6617.             m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 5));
  6618.             hStr = pClientDE->FormatString(lsd->nText);
  6619.             m_hLoadCursor->DrawFormat(pClientDE->GetStringData(hStr), (short)(lsd->nTextWrapWidth * ratioX));
  6620.             pClientDE->FreeString(hStr);
  6621.         }
  6622.  
  6623.         // Draw the loading screen...
  6624.         pClientDE->DrawSurfaceToSurface(hScreen, m_hLoadingScreen, DNULL, 0, 0);
  6625.  
  6626.         // Draw a loading message at the bottom of the screen
  6627.         m_hLoadCursor->SetDest(hScreen);
  6628.         m_hLoadCursor->SetFont(m_hLoadTitleFont);
  6629.         m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(screenHeight - m_hLoadTitleFont->height));
  6630.  
  6631.         if(GetGameState() == GS_WAITING)
  6632.         {
  6633.             DFLOAT        r, g, b, time = pClientDE->GetTime();
  6634.             DFLOAT        calc;
  6635.  
  6636.             if(!m_bPlayedWaitingSound)
  6637.             {
  6638.                 PlaySoundLocal( "sounds\\interface\\mainmenus\\esc01.wav", SOUNDPRIORITY_MISC_HIGH);
  6639.                 m_bPlayedWaitingSound = DTRUE;
  6640.             }
  6641.  
  6642.             if(time - m_fLoadingFadeTime >= 1.0f)
  6643.             {
  6644.                 m_fLoadingFadeTime = time;
  6645.                 m_bLoadingFadeUp = !m_bLoadingFadeUp;
  6646.             }
  6647.  
  6648.             calc = (time - m_fLoadingFadeTime) / 1.0f;
  6649.  
  6650.             if(m_bLoadingFadeUp)
  6651.             {
  6652.                 r = 0.776f + (0.224f * calc);
  6653.                 g = 0.647f - (0.647f * calc);
  6654.                 b = 0.518f - (0.518f * calc);
  6655.             }
  6656.             else
  6657.             {
  6658.                 r = 1.000f - (0.224f * calc);
  6659.                 g = 0.647f * calc;
  6660.                 b = 0.518f * calc;
  6661.             }
  6662.  
  6663.             m_hLoadCursor->DrawSolid("Press a key to continue...", pClientDE->SetupColor2(r, g, b, DFALSE));
  6664.         }
  6665.         else
  6666.         {
  6667.             hStr = pClientDE->FormatString(g_LoadScreenMessages[GetRandom(0,MAX_LOADING_MESSAGES-1)]);
  6668.             m_hLoadCursor->Draw(pClientDE->GetStringData(hStr));
  6669.             pClientDE->FreeString(hStr);
  6670.         }
  6671.     }
  6672. #endif
  6673.  
  6674.     // Free the fonts and cursor
  6675.     if(m_hLoadCursor)        { delete m_hLoadCursor; m_hLoadCursor = 0; }
  6676.     if(m_hLoadTitleFont)    { m_hLoadTitleFont->Free(); delete m_hLoadTitleFont; m_hLoadTitleFont = 0; }
  6677.     if(m_hLoadTextFont)        { m_hLoadTextFont->Free(); delete m_hLoadTextFont; m_hLoadTextFont = 0; }
  6678. }
  6679.  
  6680.  
  6681. // ----------------------------------------------------------------------- //
  6682. //
  6683. //    ROUTINE:    CBloodClientShell::Set3rdPersonCamera()
  6684. //
  6685. //    PURPOSE:    Turn on/off 3rd person camera mode
  6686. //
  6687. // ----------------------------------------------------------------------- //
  6688.  
  6689. void CBloodClientShell::Set3rdPersonCamera(DBOOL bExternal)
  6690. {
  6691.     CClientDE* pClientDE = GetClientDE();
  6692.     if (!pClientDE || !m_hCamera) return;
  6693.  
  6694.     if (bExternal && m_playerCamera.IsFirstPerson())
  6695.     {
  6696. //        m_weaponModel.SetVisible(DFALSE);
  6697.  
  6698.         m_b3rdPerson = DTRUE;
  6699.  
  6700.         m_playerCamera.GoChaseMode();
  6701.  
  6702.         m_bZoomView = DFALSE;             // Can't zoom in 3rd person...
  6703.     }
  6704.     else if (!bExternal && !m_playerCamera.IsFirstPerson()) // Go Internal
  6705.     {
  6706. //        m_weaponModel.SetVisible(DTRUE);
  6707.  
  6708.         m_b3rdPerson = DFALSE;
  6709.         m_playerCamera.GoFirstPerson();
  6710.     }
  6711.     ShowPlayer(m_b3rdPerson ? DTRUE : DFALSE);
  6712. }
  6713.  
  6714.  
  6715.  
  6716. // ----------------------------------------------------------------------- //
  6717. //
  6718. //    ROUTINE:    CBloodClientShell::UpdateCameraPosition()
  6719. //
  6720. //    PURPOSE:    Update the camera position
  6721. //
  6722. // ----------------------------------------------------------------------- //
  6723.  
  6724. void CBloodClientShell::UpdateCameraPosition()
  6725. {
  6726.     DBOOL bCameraIsListener;
  6727.     CClientDE* pClientDE = GetClientDE();
  6728.     if (!pClientDE) return;
  6729.  
  6730.     HLOCALOBJ hPlayerObj = m_pMoveMgr->GetObject();
  6731. //    HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  6732.     if (!hPlayerObj || !m_hCamera) return;
  6733.  
  6734.     DVector vPos;
  6735.     pClientDE->GetObjectPos(hPlayerObj, &vPos);
  6736.  
  6737.     // External camera
  6738.     if (m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj)
  6739.     {
  6740.         DRotation rRot;
  6741.  
  6742.         HLOCALOBJ hCameraObj = DNULL;
  6743.  
  6744.         bCameraIsListener = DTRUE;
  6745.  
  6746.         // Determine the object to use
  6747.         if (m_hSeeingEyeObj) 
  6748.             hCameraObj = m_hSeeingEyeObj;
  6749.         else if (m_hOrbObj) 
  6750.             hCameraObj = m_hOrbObj;
  6751.         else if (m_pExternalCamera) 
  6752.         {
  6753.             hCameraObj = m_pExternalCamera->GetServerObj();
  6754.             bCameraIsListener = m_pExternalCamera->IsListener( );
  6755.         }
  6756.         
  6757.         if (hCameraObj)
  6758.         {
  6759.             // Get position
  6760.             pClientDE->GetObjectPos(hCameraObj, &vPos);
  6761.             pClientDE->SetObjectPos(m_hCamera, &vPos);
  6762.  
  6763.             if (!m_hOrbObj && !m_hSeeingEyeObj)
  6764.             {
  6765.                 // Get Rotation
  6766.                 pClientDE->GetObjectRotation(hCameraObj, &rRot);
  6767.                 pClientDE->SetObjectRotation(m_hCamera, &rRot);
  6768.             }                
  6769.             else
  6770.             {
  6771.                 ROT_INIT( rRot );
  6772.             }
  6773.  
  6774.             if( bCameraIsListener )
  6775.             {
  6776.                 // Set the listener for sounds
  6777.                 pClientDE->SetListener( DFALSE, &vPos, &rRot );
  6778.             }
  6779.             else
  6780.                 pClientDE->SetListener( DTRUE, DNULL, DNULL );
  6781.         }
  6782.     }
  6783.     else
  6784.     {
  6785.         // Player camera - first person
  6786.         if (m_playerCamera.IsFirstPerson())    
  6787.         {
  6788.             DVector up;
  6789.             DVector forward;
  6790.             DVector right;
  6791.  
  6792.             if (cdata.byFlags & CDATA_CANMOVE)
  6793.             {
  6794.                 UpdateBob();
  6795.                 UpdateHeadCant();
  6796.             }
  6797.  
  6798.             pClientDE->GetRotationVectors(&m_Rotation, &up, &right, &forward);
  6799.  
  6800.             VEC_MULSCALAR(right, right, m_fBobWidth)
  6801.             VEC_ADD(vPos, vPos, right)
  6802.  
  6803.             // HACK - remove eventually
  6804.     //#ifdef _DEBUG
  6805.     //        VEC_MULSCALAR(forward, forward, m_fCameraZoom);
  6806.     //        VEC_SUB(pos, pos, forward);
  6807.     //#endif
  6808.  
  6809.             vPos.y += m_fViewY + m_fBobHeight;
  6810.  
  6811.             pClientDE->SetObjectPos(m_hCamera, &vPos);
  6812.  
  6813.     //#ifdef _DEBUG
  6814.             // HACK - remove eventually
  6815.     //        VEC_ADD(pos, pos, forward);
  6816.     //#endif
  6817.  
  6818.             // Set the listener for sounds
  6819.             pClientDE->SetListener( DTRUE, DNULL, DNULL );
  6820.         }
  6821.         // Player camera - 3rd person
  6822.         else
  6823.         {
  6824.             VEC_COPY(vPos, m_playerCamera.GetPos());
  6825.             pClientDE->SetObjectPos(m_hCamera, &vPos);
  6826.  
  6827.             ROT_COPY(m_Rotation, m_playerCamera.GetRotation());
  6828.  
  6829.             // Set the listener for sounds
  6830.             pClientDE->SetListener( DFALSE, &vPos, &m_Rotation );
  6831.         }
  6832.  
  6833.         // Update the create that's on your face
  6834.         if(m_pCreature)
  6835.             m_pCreature->Update(cdata.fPitch, cdata.fYaw, &vPos);
  6836.     }
  6837.  
  6838.     UpdateGun(&m_Rotation, &vPos);
  6839. }
  6840.  
  6841. // ----------------------------------------------------------------------- //
  6842. //
  6843. //    ROUTINE:    CBloodClientShell::CalculateCameraRotation()
  6844. //
  6845. //    PURPOSE:    Calculate the new camera rotation
  6846. //
  6847. // ----------------------------------------------------------------------- //
  6848.  
  6849. void CBloodClientShell::CalculateCameraRotation()
  6850. {
  6851.     DFLOAT offsets[3];
  6852.     DFLOAT rotateSpeed;
  6853. //    DRotation newRot;
  6854.     DFLOAT newPitch;
  6855.     DFLOAT newYaw;
  6856.     DFLOAT addPitch;
  6857.     DFLOAT addYaw;
  6858.  
  6859.     CClientDE* pClientDE = GetClientDE();
  6860.  
  6861.     newPitch = m_fPitch;
  6862.     newYaw = m_fYaw;
  6863.     addPitch = 0;
  6864.     addYaw = 0;
  6865.  
  6866.     rotateSpeed = 3 * pClientDE->GetFrameTime();
  6867.     pClientDE->GetAxisOffsets(offsets);
  6868.  
  6869.     HCONSOLEVAR hVar;
  6870.     float fAxisForwardBackward = 0.0f;
  6871.     float fAxisLeftRight = 0.0f;
  6872.     float fAxisYaw = 0.0f;
  6873.     float fAxisPitch = 0.0f;
  6874.     DBOOL bUseAxisForwardBackward = FALSE;
  6875.     DBOOL bUseAxisLeftRight = FALSE;
  6876.     DBOOL bFixedAxisPitch = FALSE;
  6877.     float fAxisYawDeadZone = 0.10f;
  6878.     float fAxisPitchDeadZone = 0.10f;
  6879.     float fAxisForwardBackwardDeadZone = 0.10f;
  6880.     float fAxisLeftRightDeadZone = 0.10f;
  6881.  
  6882.     if (m_bUseJoystick && !m_bAdvancedDisableJoystick)
  6883.     {
  6884.         hVar = pClientDE->GetConsoleVar( "AxisYawDeadZone");
  6885.         if (hVar != NULL) fAxisYawDeadZone = pClientDE->GetVarValueFloat(hVar);
  6886.         hVar = pClientDE->GetConsoleVar( "AxisPitchDeadZone");
  6887.         if (hVar != NULL) fAxisPitchDeadZone = pClientDE->GetVarValueFloat(hVar);
  6888.         hVar = pClientDE->GetConsoleVar( "AxisForwardBackwardDeadZone");
  6889.         if (hVar != NULL) fAxisForwardBackwardDeadZone = pClientDE->GetVarValueFloat(hVar);
  6890.         hVar = pClientDE->GetConsoleVar( "AxisLeftRightDeadZone");
  6891.         if (hVar != NULL) fAxisLeftRightDeadZone = pClientDE->GetVarValueFloat(hVar);
  6892.  
  6893.         hVar = pClientDE->GetConsoleVar( "AxisYaw");
  6894.         if (hVar != NULL)
  6895.         {
  6896.             fAxisYaw = pClientDE->GetVarValueFloat(hVar);
  6897.             if ((fAxisYaw > fAxisYawDeadZone) || ((fAxisYaw < -fAxisYawDeadZone))) offsets[0] += fAxisYaw;
  6898.         }
  6899.         hVar = pClientDE->GetConsoleVar( "AxisPitch");
  6900.         if (hVar != NULL) 
  6901.         {
  6902.             fAxisPitch = pClientDE->GetVarValueFloat(hVar);
  6903.             if ((fAxisPitch > fAxisPitchDeadZone) || (fAxisPitch < -fAxisPitchDeadZone)) offsets[1] += fAxisPitch;
  6904.         }
  6905.         hVar = pClientDE->GetConsoleVar( "AxisLeftRight");
  6906.         if (hVar != NULL) 
  6907.         {
  6908.             fAxisLeftRight = pClientDE->GetVarValueFloat(hVar);
  6909.             bUseAxisLeftRight = TRUE;
  6910.         }
  6911.         hVar = pClientDE->GetConsoleVar( "AxisForwardBackward");
  6912.         if (hVar != NULL)
  6913.         {
  6914.             fAxisForwardBackward = pClientDE->GetVarValueFloat(hVar);
  6915.             bUseAxisForwardBackward = TRUE;
  6916.         }
  6917.  
  6918.         hVar = pClientDE->GetConsoleVar( "FixedAxisPitch");
  6919.         if (hVar != NULL) if (pClientDE->GetVarValueFloat(hVar) == 1) 
  6920.         {
  6921.             newPitch = fAxisPitch;
  6922.             bFixedAxisPitch = TRUE;
  6923. //        pClientDE->CPrint("FixedAxisPitch==1 AxisPitch=%14.6f",(double)fAxisPitch); // BLB TEMP
  6924.         }
  6925.     }
  6926.  
  6927.     m_pMoveMgr->UpdateAxisMovement(bUseAxisForwardBackward, fAxisForwardBackward, fAxisForwardBackwardDeadZone, bUseAxisLeftRight, fAxisLeftRight, fAxisLeftRightDeadZone);
  6928.  
  6929.     cdata.MouseAxis0 = offsets[0];
  6930.     cdata.MouseAxis1 = offsets[1];
  6931.  
  6932. //    if (cdata.byFlags & CDATA_MOUSEAIMING)
  6933.     if (m_bMouseLook || pClientDE->IsCommandOn(COMMAND_MOUSEAIMTOGGLE))
  6934.     {
  6935.         DFLOAT addPitch = m_bZoomView ? (offsets[1] / 4.0f) : (offsets[1]);
  6936.         addPitch *= (IsMouseInvertYAxis() ? -1 : 1);
  6937.         newPitch += addPitch;
  6938.     }
  6939.  
  6940.     // Only allow input if not editing and movement is not blocked
  6941.     if (!m_MessageMgr.GetEditingState() && (cdata.byFlags & CDATA_CANMOVE || m_hOrbObj || m_hSeeingEyeObj))
  6942.     {
  6943.         // Rotate if not strafe state
  6944.         if (!pClientDE->IsCommandOn(COMMAND_STRAFE))
  6945.         {
  6946.             newYaw += (m_bZoomView) ? (offsets[0] / 4.0f) : offsets[0];
  6947.  
  6948.             if (pClientDE->IsCommandOn(COMMAND_LEFT))
  6949.                 newYaw -= rotateSpeed * GetKeyboardTurnRate();
  6950.             else if (pClientDE->IsCommandOn(COMMAND_RIGHT))
  6951.                 newYaw += rotateSpeed * GetKeyboardTurnRate();
  6952.         }
  6953.  
  6954.         // Turn around
  6955.         if (pClientDE->IsCommandOn(COMMAND_TURNAROUND) && m_SpinAmount == 0)
  6956.         {
  6957.             m_SpinAmount = - PI;
  6958.         }
  6959.         else if (m_SpinAmount != 0)
  6960.         {
  6961.             DFLOAT nSpin;
  6962.  
  6963.             nSpin = pClientDE->GetFrameTime() * 15;
  6964.             m_SpinAmount += nSpin;
  6965.             
  6966.             if (m_SpinAmount > 0)
  6967.             {
  6968.                 nSpin -= m_SpinAmount;
  6969.                 m_SpinAmount = 0;
  6970.             }
  6971.  
  6972.             newYaw += nSpin;
  6973.         }
  6974.  
  6975.         // Aim Up/Down
  6976.         if (pClientDE->IsCommandOn(COMMAND_AIMUP) && !m_bZeroXAngle)
  6977.             newPitch -= rotateSpeed;
  6978.         else if (pClientDE->IsCommandOn(COMMAND_AIMDOWN) && !m_bZeroXAngle)
  6979.             newPitch += rotateSpeed;
  6980.  
  6981.         // Look Up/Down
  6982.         if (pClientDE->IsCommandOn(COMMAND_LOOKUP))
  6983.             newPitch -= rotateSpeed;
  6984.         else if  (pClientDE->IsCommandOn(COMMAND_LOOKDOWN))
  6985.             newPitch += rotateSpeed;
  6986.     }
  6987.  
  6988.     // Zero X Angle (if we just let go of a look key)
  6989.     if (m_bZeroXAngle)
  6990.     {
  6991.         if (newPitch != 0)
  6992.         {
  6993.             DFLOAT nSpin;
  6994.             DFLOAT nNewX;
  6995.  
  6996.             if (newPitch <= 0)
  6997.                 nSpin = rotateSpeed;
  6998.             else
  6999.                 nSpin = -rotateSpeed;
  7000.  
  7001.             nNewX = newPitch + nSpin;
  7002.  
  7003.             if (newPitch > 0 && nNewX <= 0)
  7004.                 newPitch = 0;
  7005.             else if (newPitch < 0 && nNewX >= 0)
  7006.                 newPitch = 0;
  7007.             else
  7008.                 newPitch = nNewX;
  7009.  
  7010.         }
  7011.         if (newPitch == 0)
  7012.             m_bZeroXAngle = DFALSE;
  7013.     }
  7014.  
  7015.     if (m_fViewKick)
  7016.     {
  7017.         addPitch -= DEG2RAD(m_fViewKick);
  7018.     }
  7019.     
  7020.     if (m_fKickTime)
  7021.     {
  7022.         m_fKickTime -= pClientDE->GetFrameTime();
  7023.         if (m_fKickTime <= 0)
  7024.         {
  7025.             m_fKickTime = 0.001f;
  7026.             m_fViewKick -= RAD2DEG(rotateSpeed);
  7027.             if (m_fViewKick <= 0)
  7028.             {
  7029.                 m_fViewKick = 0;
  7030.                 m_fKickTime = 0;
  7031.             }
  7032.         }
  7033.     }
  7034.  
  7035.     DFLOAT minY = (PI / 2) - 0.01f;
  7036.  
  7037.     if (newPitch < -minY) 
  7038.         newPitch = -minY;
  7039.     if (newPitch > minY) 
  7040.         newPitch = minY;
  7041.  
  7042.     if (newPitch + addPitch != cdata.fPitch || newYaw + addYaw != cdata.fYaw)
  7043.     {
  7044.         cdata.fPitch = newPitch + addPitch;
  7045.         m_fPitch = newPitch;
  7046.         cdata.fYaw = newYaw + addYaw;
  7047.         m_fYaw = newYaw;
  7048. //        pClientDE->CPrint("Pitch=%14.6f Yaw=%14.6f",(double)m_fPitch,(double)m_fYaw); // BLB TEMP
  7049.     }
  7050. }
  7051.  
  7052.  
  7053. // ----------------------------------------------------------------------- //
  7054. //
  7055. //    ROUTINE:    CBloodClientShell::UpdateCameraRotation()
  7056. //
  7057. //    PURPOSE:    Set the new camera rotation
  7058. //
  7059. // ----------------------------------------------------------------------- //
  7060.  
  7061. void CBloodClientShell::UpdateCameraRotation()
  7062. {
  7063.     CClientDE* pClientDE = GetClientDE();
  7064.     if (!pClientDE || !m_hCamera) return;
  7065.  
  7066.     HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  7067.     if (!hPlayerObj) return;
  7068.  
  7069.     if (m_bDemoPlayback)
  7070.     {
  7071.         // Just get camera angles from the object...
  7072.  
  7073.         pClientDE->GetObjectRotation(hPlayerObj, &m_Rotation);
  7074.         pClientDE->SetObjectRotation(m_hCamera, &m_Rotation);
  7075.         return;
  7076.     }
  7077.  
  7078.  
  7079.     // Setup the pitch and roll
  7080.     pClientDE->SetupEuler(&m_Rotation, cdata.fPitch, cdata.fYaw, 0);
  7081.  
  7082.     // Rotate the head canting amount around vF
  7083.     DVector vU, vF, vR;
  7084.     pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &vF);
  7085.     pClientDE->RotateAroundAxis(&m_Rotation, &vF, m_fCamCant + m_fBobCant + m_fShakeCant);
  7086.     
  7087.     if (m_pExternalCamera)
  7088.     {
  7089.         // Just calculate the correct player rotation...
  7090.     }
  7091.     else if (m_playerCamera.IsFirstPerson())
  7092.     {
  7093.         pClientDE->SetObjectRotation(m_hCamera, &m_Rotation);
  7094.     }
  7095.     else
  7096.     {
  7097.         // Set the camera to use the rotation calculated by the player camera,
  7098.         // however we still need to calculate the correct rotation to be sent
  7099.         // to the player...
  7100.  
  7101.         DRotation rRot = m_playerCamera.GetRotation();
  7102.         pClientDE->SetObjectRotation(m_hCamera, &rRot);
  7103.     }
  7104. }
  7105.  
  7106.  
  7107.  
  7108. // ----------------------------------------------------------------------- //
  7109. //
  7110. //    ROUTINE:    CBloodClientShell::GetWorldTitle()
  7111. //
  7112. //    PURPOSE:    Parse the world title from the WorldInfo string
  7113. //
  7114. // ----------------------------------------------------------------------- //
  7115.  
  7116. void CBloodClientShell::GetWorldTitle(char *pWorldFile)
  7117. {
  7118.     CClientDE* pClientDE = GetClientDE();
  7119.     if (!pClientDE || !pWorldFile) return;
  7120.  
  7121.     HSTRING    hstrTitle = DNULL;
  7122.     char szFilename[MAX_CS_FILENAME_LEN+1];
  7123.     char szWorldInfo[255];
  7124.  
  7125. #ifdef _ADDON
  7126.     char sUpr[256];
  7127.     strncpy(sUpr, pWorldFile, 255);
  7128.     strupr(sUpr);
  7129.     if (strstr(sUpr, "WORLDS_AO"))
  7130.     {
  7131.         strncpy(szFilename, pWorldFile, MAX_CS_FILENAME_LEN);
  7132.         if (!strstr(sUpr, ".DAT"))
  7133.         {
  7134.             strcat(szFilename, ".dat");
  7135.         }
  7136.     }
  7137.     else
  7138.     {
  7139.         sprintf(szFilename, "Worlds\\%s.dat", pWorldFile);
  7140.     }
  7141. #else
  7142.     sprintf(szFilename, "Worlds\\%s.dat", pWorldFile);
  7143. #endif
  7144.  
  7145.     DDWORD dwInfoLen;
  7146.     if(pClientDE->GetWorldInfoString(szFilename, szWorldInfo, 255, &dwInfoLen) == LT_OK)
  7147.     {
  7148.         int nArgs;
  7149.     
  7150.         char tokenSpace[64*20];
  7151.         char *pTokens[64];
  7152.         char *pCommand = szWorldInfo;
  7153.         char *pCommandPos;
  7154.  
  7155.         DBOOL bDone = DFALSE;
  7156.         while (!bDone)
  7157.         {
  7158.             if (!pClientDE->Parse(pCommand, &pCommandPos, tokenSpace, pTokens, &nArgs))
  7159.                 bDone = DTRUE;
  7160.             else
  7161.                 pCommand = pCommandPos;
  7162.  
  7163.             for(int i = 0; i < nArgs; i++)
  7164.             {
  7165.                 if(pTokens[i])
  7166.                 {
  7167.                     if((_mbsicmp((const unsigned char*)"worldname", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1])
  7168.                     {
  7169.                         m_hstrTitle = pClientDE->CreateString(pTokens[i+1]);
  7170.                     }
  7171.                     else if((_mbsicmp((const unsigned char*)"loadscreen", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1])
  7172.                     {
  7173. #ifdef _DEMO
  7174.                         strupr(szFilename);
  7175.                         if (_mbsstr((const unsigned char*)szFilename, (const unsigned char*)"DEMO_02"))
  7176.                             m_hstrLoadScreen = pClientDE->CreateString("\\screens\\loading2.pcx");
  7177.                         else
  7178.                             m_hstrLoadScreen = pClientDE->CreateString("\\screens\\loading1.pcx");
  7179. #else
  7180.                         char szLoadScreen[128];
  7181.                         sprintf(szLoadScreen, "Interface\\LoadScreens\\%s", pTokens[i+1]);
  7182.                         m_hstrLoadScreen = pClientDE->CreateString(szLoadScreen);
  7183. #endif
  7184.  
  7185.                     }
  7186.                     else if((_mbsicmp((const unsigned char*)"loadscreenID", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1])
  7187.                     {
  7188.                         m_nLoadScreenID = (DDWORD)atoi(pTokens[i+1]);
  7189.                     }
  7190.                 }
  7191.             }
  7192.         }
  7193.     }
  7194.  
  7195.  
  7196.     // Make sure we have a title...
  7197.  
  7198.     if(!m_hstrTitle)
  7199.         m_hstrTitle = pClientDE->CreateString(pWorldFile);
  7200.  
  7201.  
  7202.     // Change the loading screen string if this is a nightmare level...
  7203.  
  7204. #ifdef _ADDON
  7205.     strupr(szFilename);
  7206.     if (strstr(szFilename, "WORLDS_AO"))
  7207.     {
  7208.         if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; }
  7209.         m_hstrLoadScreen = pClientDE->CreateString("Screens_ao\\Bumper.pcx");
  7210.     }
  7211. #endif
  7212.  
  7213. }
  7214.  
  7215.  
  7216. // --------------------------------------------------------------------------- //
  7217. //
  7218. //    ROUTINE:    LoadLeakFile
  7219. //
  7220. //    PURPOSE:    Loads a leak file and creates a line system for it.
  7221. //
  7222. // --------------------------------------------------------------------------- //
  7223.  
  7224. DBOOL LoadLeakFile(ClientDE *pClientDE, char *pFilename)
  7225. {
  7226.     FILE *fp;
  7227.     char line[256];
  7228.     HLOCALOBJ hObj;
  7229.     ObjectCreateStruct cStruct;
  7230.     DELine theLine;
  7231.     int nRead;
  7232.  
  7233.     fp = fopen(pFilename, "rt");
  7234.     if(fp)
  7235.     {
  7236.         INIT_OBJECTCREATESTRUCT(cStruct);
  7237.         cStruct.m_ObjectType = OT_LINESYSTEM;
  7238.         cStruct.m_Flags = FLAG_VISIBLE;
  7239.         hObj = pClientDE->CreateObject(&cStruct);
  7240.         if(!hObj)
  7241.         {
  7242.             fclose(fp);
  7243.             return DFALSE;
  7244.         }
  7245.  
  7246.         while(fgets(line, 256, fp))
  7247.         {
  7248.             nRead = sscanf(line, "%f %f %f %f %f %f", 
  7249.                 &theLine.m_Points[0].m_Pos.x, &theLine.m_Points[0].m_Pos.y, &theLine.m_Points[0].m_Pos.z, 
  7250.                 &theLine.m_Points[1].m_Pos.x, &theLine.m_Points[1].m_Pos.y, &theLine.m_Points[1].m_Pos.z);
  7251.  
  7252.             theLine.m_Points[0].r = theLine.m_Points[0].g = theLine.m_Points[0].b = 1;
  7253.             theLine.m_Points[0].a = 1;
  7254.             
  7255.             theLine.m_Points[1].r = 1;
  7256.             theLine.m_Points[1].g = theLine.m_Points[1].b = 0;
  7257.             theLine.m_Points[1].a = 1;
  7258.  
  7259.             pClientDE->AddLine(hObj, &theLine);
  7260.         }
  7261.  
  7262.         fclose(fp);
  7263.         return DTRUE;
  7264.     }
  7265.     else
  7266.     {
  7267.         return DFALSE;
  7268.     }
  7269. }
  7270.  
  7271. /*
  7272. // ----------------------------------------------------------------------- //
  7273. //
  7274. //    ROUTINE:    LoadConfig
  7275. //
  7276. //    PURPOSE:    Reads player config data
  7277. //
  7278. // ----------------------------------------------------------------------- //
  7279. DBOOL LoadConfig(char* pfilename, ConfigStruct *pConfig) 
  7280. {
  7281.     FILE *infile;
  7282.     char line[256];
  7283.     char *tokenname;
  7284.     char *tokenvalue;
  7285.  
  7286.     if (!(infile = fopen(pfilename, "r")))
  7287.         return DFALSE;
  7288.  
  7289.     while (fgets(line, 256, infile) != NULL)
  7290.     {
  7291.         // Get tokens, see if first one is a comment
  7292.         if (!(tokenname = strtok(line, " \t")) || tokenname[0] == ';')
  7293.             continue;
  7294.         if (!(tokenvalue = strtok(NULL, " \t\r\n")))
  7295.             continue;
  7296.         
  7297.         _strupr(tokenname);
  7298.  
  7299.         // Check for attributes
  7300.         if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"STRENGTH"))
  7301.             pConfig->nStrength = atoi(tokenvalue);
  7302.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"MAGIC"))
  7303.             pConfig->nMagic = atoi(tokenvalue);
  7304.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPEED"))
  7305.             pConfig->nSpeed = atoi(tokenvalue);
  7306.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"RESISTANCE"))
  7307.             pConfig->nResistance = atoi(tokenvalue);
  7308.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"NAME"))
  7309.             _mbscpy(pConfig->szName, tokenvalue);
  7310.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"CHARACTER"))
  7311.             pConfig->nCharacter = atoi(tokenvalue);
  7312.         // Check for bindings
  7313.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING1"))
  7314.             pConfig->nBindingSlots[0] = atoi(tokenvalue);
  7315.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING2"))
  7316.             pConfig->nBindingSlots[1] = atoi(tokenvalue);
  7317.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING3"))
  7318.             pConfig->nBindingSlots[2] = atoi(tokenvalue);
  7319.         // Check for weapons
  7320.         // Slot 1 is always melee
  7321. //        else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP1"))
  7322. //            pConfig->nWeaponSlots[0] = atoi(tokenvalue);
  7323.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP2"))
  7324.             pConfig->nWeaponSlots[1] = atoi(tokenvalue);
  7325.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP3"))
  7326.             pConfig->nWeaponSlots[2] = atoi(tokenvalue);
  7327.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP4"))
  7328.             pConfig->nWeaponSlots[3] = atoi(tokenvalue);
  7329.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP5"))
  7330.             pConfig->nWeaponSlots[4] = atoi(tokenvalue);
  7331.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP6"))
  7332.             pConfig->nWeaponSlots[5] = atoi(tokenvalue);
  7333.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP7"))
  7334.             pConfig->nWeaponSlots[6] = atoi(tokenvalue);
  7335.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP8"))
  7336.             pConfig->nWeaponSlots[7] = atoi(tokenvalue);
  7337.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP9"))
  7338.             pConfig->nWeaponSlots[8] = atoi(tokenvalue);
  7339.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP0"))
  7340.             pConfig->nWeaponSlots[9] = atoi(tokenvalue);
  7341.         // Check for inventory items
  7342.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV1"))
  7343.             pConfig->nItemSlots[0] = atoi(tokenvalue);
  7344.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV2"))
  7345.             pConfig->nItemSlots[1] = atoi(tokenvalue);
  7346.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV3"))
  7347.             pConfig->nItemSlots[2] = atoi(tokenvalue);
  7348.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV4"))
  7349.             pConfig->nItemSlots[3] = atoi(tokenvalue);
  7350.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"PROXIMITYBOMBS"))
  7351.             pConfig->nProximityBombs = atoi(tokenvalue);
  7352.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"REMOTEBOMBS"))
  7353.             pConfig->nRemoteBombs = atoi(tokenvalue);
  7354.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SMOKEBOMBS"))
  7355.             pConfig->nSmokeBombs = atoi(tokenvalue);
  7356.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"TIMEBOMBS"))
  7357.             pConfig->nTimeBombs = atoi(tokenvalue);
  7358.         // Check for spells
  7359.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL1"))
  7360.             pConfig->nSpellSlots[0] = atoi(tokenvalue);
  7361.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL2"))
  7362.             pConfig->nSpellSlots[1] = atoi(tokenvalue);
  7363.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL3"))
  7364.             pConfig->nSpellSlots[2] = atoi(tokenvalue);
  7365.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL4"))
  7366.             pConfig->nSpellSlots[3] = atoi(tokenvalue);
  7367.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL5"))
  7368.             pConfig->nSpellSlots[4] = atoi(tokenvalue);
  7369.         else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL6"))
  7370.             pConfig->nSpellSlots[5] = atoi(tokenvalue);
  7371.     }
  7372.     fclose(infile);
  7373.  
  7374.     return DTRUE;
  7375. }
  7376. */
  7377.  
  7378. /*
  7379. void CBloodClientShell::ImplementMusicSource (CClientDE* pClientDE)
  7380. {
  7381.     if (!pClientDE || !pClientShell) return;
  7382.  
  7383.     char str[64];
  7384.     switch (nMusicSource)
  7385.     {
  7386.         // Disable music...
  7387.         case 0:
  7388.         {
  7389.             _mbscpy (str, "musicenable 0");
  7390.             pClientDE->RunConsoleString (str);
  7391.         }
  7392.         break;
  7393.  
  7394.         // Use IMA...
  7395.         case 1:
  7396.         {
  7397.             _mbscpy (str, "musicenable 1");
  7398.             pClientDE->RunConsoleString (str);
  7399.  
  7400.             if (GetMusic()->IsInitialized())
  7401.             {
  7402.                 // Only re-init if not already using ima...
  7403.                 if (!GetMusic()->UsingIMA())
  7404.                 {
  7405.                     // preserve the music level, just in case we come back to ima...
  7406.                     CMusic::EMusicLevel level;
  7407.                     level = GetMusic()->GetMusicLevel();
  7408.                     if (GetMusic()->Init (pClientDE, DTRUE))
  7409.                     {
  7410.                         // Only start the music if we are in a world...
  7411.                         if (IsInWorld() && !pClientShell->IsFirstUpdate())
  7412.                         {
  7413.                             GetMusic()->InitPlayLists();
  7414.                             GetMusic()->PlayMusicLevel (level);
  7415.                         }
  7416.                     }
  7417.                 }
  7418.             }
  7419.             // music should already be inited, but let try again...
  7420.             else if (pClientShell->GetMusic()->Init (pClientDE, DTRUE))
  7421.             {
  7422.                 // Only re-init the play lists if we have been in world for a while...
  7423.                 if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate())
  7424.                     pClientShell->GetMusic()->InitPlayLists();
  7425.             }
  7426.         }
  7427.         break;
  7428.  
  7429.         // Use CD Audio...
  7430.         case 2:
  7431.         {
  7432.             _mbscpy (str, "musicenable 1");
  7433.             pClientDE->RunConsoleString (str);
  7434.  
  7435.             if (pClientShell)
  7436.             {
  7437.                 if (pClientShell->GetMusic()->IsInitialized())
  7438.                 {
  7439.                     if (pClientShell->GetMusic()->UsingIMA())
  7440.                     {
  7441.                         // preserve the music level, just in case we come back to ima...
  7442.                         CMusic::EMusicLevel level;
  7443.                         level = pClientShell->GetMusic()->GetMusicLevel();
  7444.                         if (pClientShell->GetMusic()->Init (pClientDE, DFALSE))
  7445.                         {
  7446.                             // Only start the music if we are in a world...
  7447.                             if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate())
  7448.                             {
  7449.                                 pClientShell->GetMusic()->InitPlayLists();
  7450.                                 pClientShell->GetMusic()->SetMusicLevel (level);
  7451.                                 pClientShell->GetMusic()->PlayCDList();
  7452.                             }
  7453.                         }
  7454.                     }
  7455.                 }
  7456.                 // music should already be inited, but let try again...
  7457.                 else if (pClientShell->GetMusic()->Init (pClientDE, DTRUE))
  7458.                 {
  7459.                     // Only re-init the play lists if we have been in world for a while...
  7460.                     if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate())
  7461.                     {
  7462.                         pClientShell->GetMusic()->InitPlayLists();
  7463.                         pClientShell->GetMusic()->PlayCDList();
  7464.                     }
  7465.                 }
  7466.             }
  7467.         }
  7468.         break;
  7469.     }
  7470. }
  7471.  
  7472. void CBloodClientShell::ImplementMusicVolume (CClientDE* pClientDE)
  7473. {
  7474.     if (!pClientDE) return;
  7475.  
  7476.     pClientDE->SetMusicVolume (nMusicVolume);
  7477.  
  7478.     char strConsole[64];
  7479.     sprintf (strConsole, "MusicVolume %d", nMusicVolume);
  7480.     pClientDE->RunConsoleString (strConsole);
  7481. }
  7482.  
  7483. void CBloodClientShell::ImplementSoundVolume (CClientDE* pClientDE)
  7484. {
  7485.     if (!pClientDE) return;
  7486.  
  7487.     pClientDE->SetSoundVolume (nSoundVolume);
  7488.  
  7489.     char strConsole[64];
  7490.     sprintf (strConsole, "SoundVolume %d", nSoundVolume);
  7491.     pClientDE->RunConsoleString (strConsole);
  7492. }
  7493.  
  7494. */
  7495.  
  7496.  
  7497. #ifdef BRANDED
  7498. void CBloodClientShell::CreateBrandSurface()
  7499. {
  7500.     CClientDE* pClientDE = GetClientDE();
  7501.     if (!pClientDE) return;
  7502.  
  7503.     if (!m_hBrandSurface)
  7504.     {
  7505.         HSTRING hString = pClientDE->FormatString(IDS_BRAND, "Review Copy:");
  7506.  
  7507.         if (hString)
  7508.         {
  7509.             HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE);
  7510.             HDECOLOR hTrans = pClientDE->SetupColor2 (0, 0, 0, DFALSE);
  7511.  
  7512.             HDEFONT hFont = pClientDE->CreateFont ("Arial", 6, 12, DFALSE, DFALSE, DTRUE);
  7513.             m_hBrandSurface = pClientDE->CreateSurfaceFromString (hFont, hString, hForeground, hTrans, 10, 0);
  7514.  
  7515.             pClientDE->FreeString(hString);
  7516.             pClientDE->DeleteFont (hFont);
  7517.         }
  7518.     }
  7519. }
  7520.  
  7521.  
  7522. void CBloodClientShell::DrawBrandString(HSURFACE hScreenSurface)
  7523. {
  7524.     CClientDE* pClientDE = GetClientDE();
  7525.     if (!pClientDE) return;
  7526.  
  7527.     if (m_hBrandSurface)
  7528.     {
  7529.         HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE);
  7530.         HDECOLOR hTrans = pClientDE->SetupColor2 (0, 0, 0, DFALSE);
  7531.  
  7532.         DDWORD dwWidth, dwHeight;
  7533.         DDWORD dwScreenWidth, dwScreenHeight;
  7534.         pClientDE->GetSurfaceDims(m_hBrandSurface, &dwWidth, &dwHeight);
  7535.         pClientDE->GetSurfaceDims(hScreenSurface, &dwScreenWidth, &dwScreenHeight);
  7536.  
  7537.         pClientDE->DrawSurfaceToSurfaceTransparent (hScreenSurface, m_hBrandSurface, NULL, (dwScreenWidth - dwWidth - 1), (dwScreenHeight - dwHeight - 1), hTrans);
  7538.     }
  7539. }
  7540.  
  7541. #endif // BRANDED
  7542.  
  7543.  
  7544. // --------------------------------------------------------------------------- //
  7545. //
  7546. //    ROUTINE:    ConnectToTcpIpAddress
  7547. //
  7548. //    PURPOSE:    Connects (joins) to the given tcp/ip address
  7549. //
  7550. // --------------------------------------------------------------------------- //
  7551.  
  7552. DBOOL ConnectToTcpIpAddress(CClientDE* pClientDE, char* sAddress)
  7553. {
  7554.     // Sanity checks...
  7555.  
  7556.     if (!pClientDE) return(DFALSE);
  7557.     if (!sAddress) return(DFALSE);
  7558.  
  7559.  
  7560.     // Try to connect to the given address...
  7561.  
  7562.     DBOOL db = NetStart_DoConsoleConnect(pClientDE, sAddress);
  7563.  
  7564.     if (!db)
  7565.     {
  7566.         if (_mbstrlen(sAddress) <= 0) pClientDE->CPrint("Unable to connect");
  7567.         else pClientDE->CPrint("Unable to connect to %s", sAddress);
  7568.         return(DFALSE);
  7569.     }
  7570.  
  7571.  
  7572.     // All done...
  7573.  
  7574.     if (_mbstrlen(sAddress) > 0) pClientDE->CPrint("Connected to %s", sAddress);
  7575.     else pClientDE->CPrint("Connected");
  7576.  
  7577.     g_pBloodClientShell->SetGameState(GS_MPLOADINGLEVEL);
  7578.  
  7579.     return(DTRUE);
  7580. }
  7581.  
  7582. DBOOL CBloodClientShell::DoMultiplayer(DBOOL bMinimize, DBOOL bHost)
  7583. {
  7584.     CClientDE* pClientDE = GetClientDE();
  7585.     if (!pClientDE) return(DFALSE);
  7586.  
  7587.     pClientDE->PauseSounds();
  7588.         
  7589.     if (bMinimize)
  7590.     {
  7591.         NetStart_MinimizeMainWnd(pClientDE);
  7592.     }
  7593.  
  7594.     NetStart ns;
  7595.     DBOOL bRet = NetStart_DoWizard(pClientDE, &ns, bHost ? NET_HOST : NET_JOIN);
  7596.  
  7597.     pClientDE->ResumeSounds();
  7598.  
  7599.     if (bRet)
  7600.     {
  7601.         if (m_hstrTitle) { pClientDE->FreeString(m_hstrTitle); m_hstrTitle = 0; }
  7602.         if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; }
  7603.         if (m_nLoadScreenID) m_nLoadScreenID = 0;
  7604.  
  7605.         StartGameRequest req;
  7606.         memset(&req, 0, sizeof(req));
  7607.  
  7608.         if (ns.m_bHost)
  7609.         {
  7610.             req.m_Type = STARTGAME_HOST;
  7611.  
  7612.             _mbscpy((unsigned char*)req.m_WorldName, (const unsigned char*)ns.m_sLevel);
  7613.             memcpy(&req.m_HostInfo, &ns.m_NetHost, sizeof(NetHost));
  7614.  
  7615.             g_bIsHost = DTRUE;
  7616.         }
  7617.         else
  7618.         {
  7619.             req.m_Type        = STARTGAME_CLIENT;
  7620.             req.m_pNetSession = ns.m_pNetSession;
  7621.  
  7622.             if (ns.m_bHaveTcpIp)
  7623.             {
  7624.                 req.m_Type = STARTGAME_CLIENTTCP;
  7625.                 _mbscpy((unsigned char*)req.m_TCPAddress, (const unsigned char*)ns.m_sAddress);
  7626.             }
  7627.  
  7628.             g_bIsHost = DFALSE;
  7629.         }
  7630.  
  7631.         req.m_pGameInfo     = NetStart_GetGameStruct();
  7632.         req.m_GameInfoLen   = sizeof(NetGame_t);
  7633.         req.m_pClientData   = NetStart_GetClientDataStruct();
  7634.         req.m_ClientDataLen = sizeof(NetClientData_t);
  7635.     
  7636.         DRESULT dr = pClientDE->StartGame(&req);
  7637.  
  7638.         if (bMinimize)
  7639.         {
  7640.             NetStart_RestoreMainWnd();
  7641.         }
  7642.  
  7643.         if (dr != LT_OK)
  7644.         {
  7645.             return(DFALSE);
  7646.         }
  7647.     }
  7648.     else
  7649.     {
  7650.         if (bMinimize)
  7651.         {
  7652.             NetStart_RestoreMainWnd();
  7653.         }
  7654.  
  7655.         return(DFALSE);
  7656.     }
  7657.  
  7658.     NetStart_RunServerOptions(pClientDE);
  7659.     SetGameState(GS_MPLOADINGLEVEL);
  7660.  
  7661.  
  7662.     // All done...
  7663.  
  7664.     return(DTRUE);
  7665. }
  7666.  
  7667.  
  7668. // --------------------------------------------------------------------------- //
  7669. //
  7670. //    ROUTINE:    CBloodClientShell::IsMultiplayerGame()
  7671. //
  7672. //    PURPOSE:    Are we playing a multiplayer game?
  7673. //
  7674. // --------------------------------------------------------------------------- //
  7675.  
  7676. DBOOL CBloodClientShell::IsMultiplayerGame()
  7677. {
  7678.     CClientDE* pClientDE = GetClientDE();
  7679.     if (!pClientDE ) return DFALSE;
  7680.  
  7681.     int nGameMode = 0;
  7682.     pClientDE->GetGameMode(&nGameMode);
  7683.     if (nGameMode == STARTGAME_NORMAL || nGameMode == GAMEMODE_NONE) return DFALSE;
  7684.  
  7685.     return DTRUE;
  7686. }
  7687.  
  7688.  
  7689. // ----------------------------------------------------------------------- //
  7690. //
  7691. //    ROUTINE:    CBloodClientShell::PlayMovie()
  7692. //
  7693. //    PURPOSE:    Plays the given movie
  7694. //
  7695. // ----------------------------------------------------------------------- //
  7696.  
  7697. DBOOL CBloodClientShell::PlayMovie(CClientDE* pClientDE, char* sMovie, DBOOL bCheckExistOnly)
  7698. {
  7699.     // Sanity checks...
  7700.  
  7701.     if (!pClientDE) return(DFALSE);
  7702.     if (!sMovie) return(DFALSE);
  7703.  
  7704.  
  7705.     // Check if movies are disabled...
  7706.  
  7707.     if (AdvancedDisableMovies())
  7708.     {
  7709.         return(DFALSE);
  7710.     }
  7711.  
  7712.  
  7713.     // Check if we got a full path...
  7714.  
  7715.     char sMoviePath[256];
  7716.  
  7717.     if (_mbsstr((const unsigned char*)sMovie, (const unsigned char*)"\\"))
  7718.     {
  7719.         _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sMovie);
  7720.     }
  7721.     else
  7722.     {
  7723.         sMoviePath[0] = '\0';
  7724.     }
  7725.  
  7726.  
  7727.     // Check if we need to look for this movie...
  7728.  
  7729.     if (sMoviePath[0] == '\0')
  7730.     {
  7731.         // Check if the movie file exists locally...
  7732.  
  7733.         if (CWinUtil::FileExist(sMovie))
  7734.         {
  7735.             _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sMovie);
  7736.         }
  7737.         else
  7738.         {
  7739.             // Look in a movies folder on the hard disk...
  7740.  
  7741.             char sTemp[256];
  7742.             sprintf(sTemp, "Movies\\%s", sMovie);
  7743.             if (CWinUtil::FileExist(sTemp))
  7744.             {
  7745.                 _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sTemp);
  7746.             }
  7747.             else
  7748.             {
  7749.                 // Look on the cd-rom...
  7750.  
  7751.                 char chCdRom = CWinUtil::GetCdRomDriveWithGame();
  7752.                 if (chCdRom == 0) return(DFALSE);
  7753.  
  7754.                 sprintf(sMoviePath, "%c:\\Movies\\%s", chCdRom, sMovie);
  7755.  
  7756.                 if (!CWinUtil::FileExist(sMoviePath)) return(DFALSE);
  7757.             }
  7758.         }
  7759.     }
  7760.  
  7761.     if (sMoviePath[0] == '\0') return(DFALSE);
  7762.  
  7763.  
  7764.     // If we are only checking for existence, return now...
  7765.  
  7766.     if (bCheckExistOnly)
  7767.     {
  7768.         return(DTRUE);
  7769.     }
  7770.  
  7771.  
  7772.     // Play the movie...
  7773.  
  7774.     DDWORD  nFlags  = PLAYBACK_FULLSCREEN;
  7775.     DRESULT nResult = pClientDE->StartVideo(sMoviePath, nFlags);
  7776.  
  7777.     if (nResult != DE_OK)
  7778.     {
  7779.         return(DFALSE);
  7780.     }
  7781.  
  7782.  
  7783.     // All done...
  7784.  
  7785.     return(DTRUE);
  7786. }
  7787.  
  7788.  
  7789. // ----------------------------------------------------------------------- //
  7790. //
  7791. //    ROUTINE:    CBloodClientShell::StartMovies()
  7792. //
  7793. //    PURPOSE:    Starts the movies and sets up the movie state for updating
  7794. //
  7795. // ----------------------------------------------------------------------- //
  7796.  
  7797. DBOOL CBloodClientShell::StartMovies(CClientDE* pClientDE)
  7798. {
  7799.     // Sanity checks...
  7800.  
  7801.     if (!pClientDE) return(DFALSE);
  7802.  
  7803. #ifdef _DEMO
  7804.     return(DFALSE);
  7805. #endif
  7806.  
  7807.  
  7808.     // Check if movies are disabled...
  7809.  
  7810.     if (AdvancedDisableMovies())
  7811.     {
  7812.         return(DFALSE);
  7813.     }
  7814.  
  7815.  
  7816.     // Make sure the movies actually exist...
  7817.  
  7818.     if (!PlayMovie(pClientDE, "Monolith.smk", DTRUE))
  7819.     {
  7820.         return(DFALSE);
  7821.     }
  7822.  
  7823.  
  7824.     // Set the movie state to the starting state...
  7825.  
  7826.     m_nMovieState = MOVIE_STARTLITH;
  7827.  
  7828.  
  7829.     // Set the game state...
  7830.  
  7831.     SetGameState(GS_MOVIES);
  7832.  
  7833.  
  7834.     // All done...
  7835.  
  7836.     return(DTRUE);
  7837. }
  7838.  
  7839.  
  7840. // ----------------------------------------------------------------------- //
  7841. //
  7842. //    ROUTINE:    CBloodClientShell::EndMovies()
  7843. //
  7844. //    PURPOSE:    Ends the movies and returns the game state
  7845. //
  7846. // ----------------------------------------------------------------------- //
  7847.  
  7848. DBOOL CBloodClientShell::EndMovies(CClientDE* pClientDE, DBOOL bShowTitle)
  7849. {
  7850.     // Sanity checks...
  7851.  
  7852.     if (!pClientDE) return(DFALSE);
  7853.  
  7854.  
  7855.     // Stop the movies...
  7856.  
  7857.     pClientDE->StopVideo();
  7858.  
  7859.     m_nMovieState = MOVIE_FINISHED;
  7860.  
  7861.  
  7862.     // Show the title screen if requested...
  7863.  
  7864. #ifdef _DEBUG
  7865.     bShowTitle = DFALSE;
  7866. #endif
  7867.  
  7868.     if (bShowTitle)
  7869.     {
  7870.  
  7871. #ifdef _ADDON
  7872.         HSURFACE hTitleSurface = Splash_Display(pClientDE, "\\screens_ao\\title.pcx", DTRUE);
  7873. #else
  7874.         HSURFACE hTitleSurface = Splash_Display(pClientDE, "\\screens\\title.pcx", DTRUE);
  7875. #endif
  7876.  
  7877.         if (hTitleSurface)
  7878.         {
  7879.  
  7880.             CWinUtil::TimedKeyWait(VK_ESCAPE, VK_RETURN, VK_SPACE, 6.0f);
  7881.             pClientDE->DeleteSurface(hTitleSurface);
  7882.             hTitleSurface = DNULL;
  7883.             CWinUtil::Sleep(50);
  7884.         }
  7885.     }
  7886.  
  7887.  
  7888.     // Reset the menu game state...
  7889.  
  7890.     CWinUtil::RemoveKeyDownMessages();
  7891.     SetGameState(GS_MENU);
  7892.     m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU);
  7893.  
  7894.  
  7895.     // All done...
  7896.  
  7897.     return(DTRUE);
  7898. }
  7899.  
  7900.  
  7901. // ----------------------------------------------------------------------- //
  7902. //
  7903. //    ROUTINE:    CBloodClientShell::AdvanceMovies()
  7904. //
  7905. //    PURPOSE:    Advanced to the next movie
  7906. //
  7907. // ----------------------------------------------------------------------- //
  7908.  
  7909. DBOOL CBloodClientShell::AdvanceMovies(CClientDE* pClientDE)
  7910. {
  7911.     // Sanity checks...
  7912.  
  7913.     if (!pClientDE) return(DFALSE);
  7914.  
  7915.  
  7916.     // Stop the current movies...
  7917.  
  7918.     pClientDE->StopVideo();
  7919.  
  7920.  
  7921.     // All done...
  7922.  
  7923.     return(DTRUE);
  7924. }
  7925.  
  7926.  
  7927. // ----------------------------------------------------------------------- //
  7928. //
  7929. //    ROUTINE:    CRiotClientShell::UpdateMoviesState()
  7930. //
  7931. //    PURPOSE:    Update movies
  7932. //
  7933. // ----------------------------------------------------------------------- //
  7934.  
  7935. void CBloodClientShell::UpdateMoviesState()
  7936. {
  7937.     // Sanity checks...
  7938.  
  7939.     CClientDE* pClientDE = GetClientDE();
  7940.     if (!pClientDE) return;
  7941.  
  7942.  
  7943.     // Update based on our current movie state...
  7944.  
  7945.     switch (m_nMovieState)
  7946.     {
  7947.         case MOVIE_STARTLITH:
  7948.         {
  7949.             if (!PlayMovie(pClientDE, "Monolith.smk"))
  7950.             {
  7951.                 EndMovies(pClientDE);
  7952.                 return;
  7953.             }
  7954.  
  7955.             m_nMovieState = MOVIE_PLAYINGLITH;
  7956.  
  7957.             break;
  7958.         }
  7959.  
  7960.         case MOVIE_PLAYINGLITH:
  7961.         {
  7962.             pClientDE->UpdateVideo();
  7963.  
  7964.             if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING)
  7965.             {
  7966.                 m_nMovieState = MOVIE_STARTGTI;
  7967.             }
  7968.  
  7969.             break;
  7970.         }
  7971.  
  7972.         case MOVIE_STARTGTI:
  7973.         {
  7974.             if (!PlayMovie(pClientDE, "Gti.smk"))
  7975.             {
  7976.                 EndMovies(pClientDE);
  7977.                 return;
  7978.             }
  7979.  
  7980.             m_nMovieState = MOVIE_PLAYINGGTI;
  7981.  
  7982.             break;
  7983.         }
  7984.  
  7985.         case MOVIE_PLAYINGGTI:
  7986.         {
  7987.             pClientDE->UpdateVideo();
  7988.  
  7989.             if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING)
  7990.             {
  7991.                 m_nMovieState = MOVIE_STARTINTRO;
  7992.  
  7993. #ifdef _ADDON
  7994.                 m_nMovieState = MOVIE_FINISHED;
  7995. #endif
  7996.  
  7997.             }
  7998.  
  7999.             break;
  8000.         }
  8001.  
  8002.         case MOVIE_STARTINTRO:
  8003.         {
  8004.             if (!PlayMovie(pClientDE, "Intro.smk"))
  8005.             {
  8006.                 EndMovies(pClientDE);
  8007.                 return;
  8008.             }
  8009.  
  8010.             m_nMovieState = MOVIE_PLAYINGINTRO;
  8011.  
  8012.             break;
  8013.         }
  8014.  
  8015.         case MOVIE_PLAYINGINTRO:
  8016.         {
  8017.             pClientDE->UpdateVideo();
  8018.  
  8019.             if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING)
  8020.             {
  8021.                 m_nMovieState = MOVIE_FINISHED;
  8022.             }
  8023.  
  8024.             break;
  8025.         }
  8026.  
  8027.         case MOVIE_FINISHED:
  8028.         default:
  8029.         {
  8030.             EndMovies(pClientDE, DTRUE);
  8031.         }
  8032.     }
  8033. }
  8034.  
  8035.  
  8036. // ----------------------------------------------------------------------- //
  8037. //
  8038. //    ROUTINE:    Abort
  8039. //
  8040. //    PURPOSE:    Aborts the game with a message and/or code
  8041. //
  8042. // ----------------------------------------------------------------------- //
  8043.  
  8044. void Abort(char* sErrorMsg, DDWORD dwCode)
  8045. {
  8046.     // Sanity checks...
  8047.  
  8048.     if (!g_pBloodClientShell) return;
  8049.     if (!g_pBloodClientShell->GetClientDE()) return;
  8050.  
  8051.  
  8052.     // Check if we've already aborted...
  8053.  
  8054.     if (g_bAborting)
  8055.     {
  8056.         return;
  8057.     }
  8058.  
  8059.     g_bAborting = DTRUE;
  8060.  
  8061.  
  8062.     // Build the error string...
  8063.  
  8064.     char sText[256];
  8065.  
  8066.     if (dwCode != 0)
  8067.     {
  8068.         sprintf(sText, "%s (%lu)", sErrorMsg, dwCode);
  8069.     }
  8070.     else
  8071.     {
  8072.         _mbscpy((unsigned char*)sText, (const unsigned char*)sErrorMsg);
  8073.     }
  8074.  
  8075.  
  8076.     // Shutdown the engine with an error message...
  8077.  
  8078.     g_pBloodClientShell->GetClientDE()->ShutdownWithMessage(sText);
  8079. }
  8080.  
  8081. void Abort(int nErrorID, DDWORD dwCode)
  8082. {
  8083.     // Sanity checks...
  8084.  
  8085.     if (!g_pBloodClientShell) return;
  8086.     if (!g_pBloodClientShell->GetClientDE()) return;
  8087.  
  8088.  
  8089.     // Load the string...
  8090.  
  8091.     char sText[256];
  8092.  
  8093.     HSTRING hString = g_pBloodClientShell->GetClientDE()->FormatString(nErrorID);
  8094.     if (!hString)
  8095.     {
  8096.         hString = g_pBloodClientShell->GetClientDE()->FormatString(IDS_ERR_GENERIC);
  8097.     }
  8098.  
  8099.     if (hString)
  8100.     {
  8101.         _mbscpy((unsigned char*)sText, (const unsigned char*)g_pBloodClientShell->GetClientDE()->GetStringData(hString));
  8102.         g_pBloodClientShell->GetClientDE()->FreeString(hString);
  8103.     }
  8104.     else
  8105.     {
  8106.         _mbscpy((unsigned char*)sText, (const unsigned char*)"ERROR - Unable to continue the game.");
  8107.     }
  8108.  
  8109.  
  8110.     // Let the main function do the real work...
  8111.  
  8112.     Abort(sText, dwCode);
  8113. }
  8114.  
  8115.  
  8116. // ----------------------------------------------------------------------- //
  8117. //
  8118. //    ROUTINE:    CBloodClientShell::MenuQuit
  8119. //
  8120. //    PURPOSE:    Quits the game immediately
  8121. //
  8122. // ----------------------------------------------------------------------- //
  8123.  
  8124. DBOOL CBloodClientShell::MenuQuit()
  8125. {
  8126.     // Shutdown everything...
  8127.  
  8128.     CClientDE* pClientDE = GetClientDE();
  8129.     if (!pClientDE) return(DFALSE);
  8130.  
  8131.     pClientDE->Shutdown();
  8132.  
  8133.  
  8134.     // All done...
  8135.  
  8136.     return(DTRUE);
  8137. }
  8138.  
  8139.  
  8140. // ----------------------------------------------------------------------- //
  8141. //
  8142. //    ROUTINE:    CBloodClientShell::MenuNewGame
  8143. //
  8144. //    PURPOSE:    Starts new game at the given difficulty level
  8145. //
  8146. //    COMMENT:    nDifficulty must be one of: DIFFICULTY_EASY,
  8147. //                DIFFICULTY_MEDIUM, or DIFFICULTY_HARD.
  8148. //
  8149. // ----------------------------------------------------------------------- //
  8150.  
  8151. DBOOL CBloodClientShell::MenuNewGame(int nDifficulty, int nCharacter, int nGameType)
  8152. {
  8153.     // Remove the current save info...
  8154.  
  8155.     m_SavedGameInfo.ClearSaveSlot(SLOT_CURRENT);
  8156.  
  8157.  
  8158.     // Set the starting level...
  8159.  
  8160. #ifdef _DEMO
  8161.     char* sFirstLevel = "Demo_01";
  8162. #else
  8163.     char* sFirstLevel = "01_SubwayA";
  8164. #endif
  8165.  
  8166.  
  8167.     // Set some starting flags...
  8168.  
  8169.     m_bFirstWorld = DTRUE;
  8170.  
  8171.     g_pClientDE->RunConsoleString("maxfps 0");
  8172.  
  8173.  
  8174.     // Fill in the character info...
  8175.  
  8176.     if (!SetCharacterInfo(nCharacter, MULTIPLAY_SKIN_NORMAL))
  8177.     {
  8178.         return(DFALSE);
  8179.     }
  8180.  
  8181.  
  8182.     // Start the game at the given character and difficulty...
  8183.  
  8184.     return(StartNewGame(sFirstLevel, STARTGAME_NORMAL, nGameType, LOADTYPE_NEW_GAME, nDifficulty));
  8185. }
  8186.  
  8187.  
  8188. // ----------------------------------------------------------------------- //
  8189. //
  8190. //    ROUTINE:    CBloodClientShell::MenuNewNightmaresGame
  8191. //
  8192. //    PURPOSE:    Starts new nightmares game at the given difficulty level
  8193. //
  8194. // ----------------------------------------------------------------------- //
  8195.  
  8196. DBOOL CBloodClientShell::MenuNewNightmaresGame(int nDifficulty)
  8197. {
  8198.     // Remove the current save info...
  8199.  
  8200.     m_SavedGameInfo.ClearSaveSlot(SLOT_CURRENT);
  8201.  
  8202.  
  8203.     // Set the starting level...
  8204.  
  8205.     char* sFirstLevel = "worlds_ao\\caleb1_cc_c";
  8206.  
  8207.  
  8208.     // Set some starting flags...
  8209.  
  8210.     m_bFirstWorld = DTRUE;
  8211.  
  8212.     g_pClientDE->RunConsoleString("maxfps 0");
  8213.  
  8214.  
  8215.     // Fill in the character info...
  8216.  
  8217.     if (!SetCharacterInfo(CHARACTER_CALEB, MULTIPLAY_SKIN_NORMAL))
  8218.     {
  8219.         return(DFALSE);
  8220.     }
  8221.  
  8222.  
  8223.     // Start the game at the given character and difficulty...
  8224.  
  8225.     return(StartNewGame(sFirstLevel, STARTGAME_NORMAL, GAMETYPE_SINGLE, LOADTYPE_NEW_GAME, nDifficulty));
  8226. }
  8227.  
  8228.  
  8229. // ----------------------------------------------------------------------- //
  8230. //
  8231. //    ROUTINE:    CBloodClientShell::MenuHostGame
  8232. //
  8233. //    PURPOSE:    Hosts a multiplayer network game
  8234. //
  8235. // ----------------------------------------------------------------------- //
  8236.  
  8237. DBOOL CBloodClientShell::MenuHostGame()
  8238. {
  8239.     // Do the multipalyer wizard and host a net game...
  8240.  
  8241.     return(DoMultiplayer(DTRUE, DTRUE));
  8242. }
  8243.  
  8244.  
  8245. // ----------------------------------------------------------------------- //
  8246. //
  8247. //    ROUTINE:    CBloodClientShell::MenuJoinGame
  8248. //
  8249. //    PURPOSE:    Joins a multiplayer network game
  8250. //
  8251. // ----------------------------------------------------------------------- //
  8252.  
  8253. DBOOL CBloodClientShell::MenuJoinGame()
  8254. {
  8255.     // Do the multipalyer wizard and join a net game...
  8256.  
  8257.     return(DoMultiplayer(DTRUE, DFALSE));
  8258. }
  8259.  
  8260.  
  8261. // ----------------------------------------------------------------------- //
  8262. //
  8263. //    ROUTINE:    CBloodClientShell::MenuCredits
  8264. //
  8265. //    PURPOSE:    Displays the credits
  8266. //
  8267. //    COMMENT:    The "lame" credits will be used if we're currently
  8268. //                in the middle of a game.
  8269. //
  8270. // ----------------------------------------------------------------------- //
  8271.  
  8272. DBOOL CBloodClientShell::MenuCredits()
  8273. {
  8274.     // If we're currently in a game, do the lame credits...
  8275.  
  8276.     if (m_bInWorld)
  8277.     {
  8278.         m_Credits.Term();
  8279.  
  8280.         CClientDE* pClientDE = GetClientDE();
  8281.         if (!pClientDE) return(DFALSE);
  8282.  
  8283.         if (!m_Credits.Init(pClientDE, this))
  8284.         {
  8285.             return(DFALSE);
  8286.         }
  8287.  
  8288.         PauseGame(DTRUE);
  8289.         SetGameState(GS_CREDITS);
  8290.  
  8291.         return(DTRUE);
  8292.     }
  8293.  
  8294.  
  8295.     // If we're not in a game, do the cool credits...
  8296.  
  8297.     return(StartNewGame("Credits", STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM));
  8298. }
  8299.  
  8300.  
  8301. // ----------------------------------------------------------------------- //
  8302. //
  8303. //    ROUTINE:    CBloodClientShell::MenuHelp
  8304. //
  8305. //    PURPOSE:    Display the help info
  8306. //
  8307. // ----------------------------------------------------------------------- //
  8308.  
  8309. DBOOL CBloodClientShell::MenuHelp()
  8310. {
  8311.     // All done...
  8312.  
  8313.     return(DTRUE);
  8314. }
  8315.  
  8316.  
  8317. // ----------------------------------------------------------------------- //
  8318. //
  8319. //    ROUTINE:    CBloodClientShell::MenuLoadGame
  8320. //
  8321. //    PURPOSE:    Loads the given game slot
  8322. //
  8323. // ----------------------------------------------------------------------- //
  8324.  
  8325. DBOOL CBloodClientShell::MenuLoadGame(int nSlot)
  8326. {
  8327.     // As we go, figure out the gametype...
  8328.  
  8329.     int nGameType  = GAMETYPE_SINGLE;
  8330.     int nCharacter = GetCharacter();
  8331.  
  8332.  
  8333.     // Check for the quick slot...
  8334.  
  8335.     if (nSlot == SLOT_QUICK)
  8336.     {
  8337.         _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gQuickSaveInfo.szCurrentLevel);
  8338.         nGameType  = m_SavedGameInfo.gQuickSaveInfo.nGameType;
  8339.         nCharacter = m_SavedGameInfo.gQuickSaveInfo.nCharacter;
  8340.     }
  8341.  
  8342.     if (nSlot == SLOT_CURRENT)
  8343.     {
  8344.         _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gCurrentSaveInfo.szCurrentLevel);
  8345.         nGameType  = m_SavedGameInfo.gCurrentSaveInfo.nGameType;
  8346.         nCharacter = m_SavedGameInfo.gCurrentSaveInfo.nCharacter;
  8347.     }
  8348.  
  8349.         
  8350.     // Check for a valid regular slot...
  8351.  
  8352.     if (nSlot != SLOT_QUICK && nSlot != SLOT_CURRENT)
  8353.     {
  8354.         if (nSlot < 0) return(DFALSE);
  8355.         if (nSlot >= MAX_SAVESLOTS) return(DFALSE);
  8356.  
  8357.         _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gSaveSlotInfo[nSlot].szCurrentLevel);
  8358.         nGameType  = m_SavedGameInfo.gSaveSlotInfo[nSlot].nGameType;
  8359.         nCharacter = m_SavedGameInfo.gSaveSlotInfo[nSlot].nCharacter;
  8360.     }
  8361.  
  8362.  
  8363.     // Make sure we have a level to load...
  8364.  
  8365.     if (_mbstrlen(m_szFilename) <= 0)
  8366.     {
  8367.         return(DFALSE);
  8368.     }
  8369.  
  8370.     // Copy slot to the current slot
  8371.     
  8372.     if (nSlot != SLOT_NONE && nSlot != SLOT_CURRENT)
  8373.     {
  8374.         m_SavedGameInfo.CopySlot(nSlot, SLOT_CURRENT);
  8375.     }
  8376.  
  8377.  
  8378.     // Special load type for current slot (autosave)
  8379.  
  8380.     DBYTE byLoadType = (nSlot == SLOT_CURRENT) ? LOADTYPE_RESTOREAUTOSAVE : LOADTYPE_RESTORESAVE;
  8381.  
  8382.  
  8383.     // Fill in the character info...
  8384.  
  8385.     if (!SetCharacterInfo(nCharacter, MULTIPLAY_SKIN_NORMAL))
  8386.     {
  8387.         return(DFALSE);
  8388.     }
  8389.  
  8390.  
  8391.     // Validate the game type...
  8392.  
  8393.     if (nGameType != GAMETYPE_SINGLE && nGameType != GAMETYPE_ACTION && nGameType != GAMETYPE_CUSTOM)
  8394.     {
  8395.         nGameType = GAMETYPE_SINGLE;
  8396.     }
  8397.  
  8398.  
  8399.     // Load the game...
  8400.  
  8401.     return(StartNewGame(m_szFilename, STARTGAME_NORMAL, nGameType, byLoadType, DIFFICULTY_MEDIUM));
  8402. }
  8403.  
  8404.  
  8405. // ----------------------------------------------------------------------- //
  8406. //
  8407. //    ROUTINE:    CBloodClientShell::MenuSaveGame
  8408. //
  8409. //    PURPOSE:    Saves the given game slot
  8410. //
  8411. // ----------------------------------------------------------------------- //
  8412.  
  8413. DBOOL CBloodClientShell::MenuSaveGame(int nSlot, DBYTE bySaveType)
  8414. {
  8415.     // Make sure we are actually in a game & still alive...
  8416.  
  8417.     if (!m_bInWorld || m_bDead) return(DFALSE);
  8418.  
  8419.  
  8420.     if (bySaveType == SAVETYPE_CURRENT)
  8421.     {
  8422.         // Make sure this is a valid slot...
  8423.  
  8424.         if (nSlot < SLOT_QUICK || nSlot >= MAX_SAVESLOTS) return(DFALSE);
  8425.  
  8426.         // Set the saved game info data so we can copy to a save slot once the server
  8427.         // tells us the save is complete (see SMSG_SAVEGAME_ACK).
  8428.  
  8429.         m_SavedGameInfo.SetReservedSlot(nSlot);
  8430.  
  8431.  
  8432.         // Change the game state to reflect the fact that we are saving the game...
  8433.  
  8434.         SetGameState(GS_SAVING);
  8435.     }
  8436.  
  8437.  
  8438.     // Tell the server to save our game...
  8439.  
  8440.     CClientDE* pClientDE = GetClientDE();
  8441.     if (!pClientDE) return(DFALSE);
  8442.  
  8443.     HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_SAVEGAME);
  8444.  
  8445.     pClientDE->WriteToMessageString(hMsg, m_szFilename);
  8446.     pClientDE->WriteToMessageByte(hMsg, bySaveType);
  8447.     SaveClientData( hMsg );
  8448.     pClientDE->EndMessage(hMsg);
  8449.  
  8450.  
  8451.     // All done...
  8452.  
  8453.     return(DTRUE);
  8454. }
  8455.  
  8456.  
  8457. // ----------------------------------------------------------------------- //
  8458. //
  8459. //    ROUTINE:    CBloodClientShell::MenuLoadCustomLevel
  8460. //
  8461. //    PURPOSE:    Loads the given custom level
  8462. //
  8463. // ----------------------------------------------------------------------- //
  8464.  
  8465. DBOOL CBloodClientShell::MenuLoadCustomLevel(char* sLevel, int nDifficulty)
  8466. {
  8467.     // Sanity checks...
  8468.  
  8469.     if (!sLevel) return(DFALSE);
  8470.     if (_mbstrlen(sLevel) <= 0) return(DFALSE);
  8471.  
  8472.  
  8473.     // Flag that we are starting a new game world...
  8474.  
  8475.     m_bFirstWorld = DTRUE;
  8476.  
  8477.  
  8478.     // Start a new game with the specified level and difficulty...
  8479.  
  8480.     return(StartNewGame(sLevel, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, nDifficulty));
  8481. }
  8482.  
  8483. // ----------------------------------------------------------------------- //
  8484. //
  8485. //    ROUTINE:    CBloodClientShell::MenuReturnToGame
  8486. //
  8487. //    PURPOSE:    Returns from the menus to the game
  8488. //
  8489. // ----------------------------------------------------------------------- //
  8490.  
  8491. DBOOL CBloodClientShell::MenuReturnToGame()
  8492. {
  8493.     if (IsInWorld())
  8494.     {
  8495.         SetGameState(GS_PLAYING);
  8496.         PauseGame(DFALSE);
  8497.  
  8498.         if (g_bLevelChange3rdPersonCam)
  8499.         {
  8500.             if (g_pClientDE) g_pClientDE->SetInputState(DFALSE);
  8501.             if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE);
  8502.             m_bDrawFragBar = DTRUE;
  8503.  
  8504.         }
  8505.  
  8506.         return DTRUE;
  8507.     }
  8508.  
  8509.     return DFALSE;
  8510. }
  8511.  
  8512. // ----------------------------------------------------------------------- //
  8513. //
  8514. //    ROUTINE:    CBloodClientShell::MenuSetDetail
  8515. //
  8516. //    PURPOSE:    Sets the detail file cfg and checks the launcher settings
  8517. //
  8518. // ----------------------------------------------------------------------- //
  8519.  
  8520. DBOOL CBloodClientShell::MenuSetDetail()
  8521. {
  8522.     CClientDE* pClientDE = GetClientDE();
  8523.     HCONSOLEVAR        hVar;
  8524.  
  8525.     // General detail settings
  8526.     hVar = pClientDE->GetConsoleVar("GlobalDetail");
  8527.     m_nGlobalDetail = (DBYTE)pClientDE->GetVarValueFloat (hVar);
  8528.  
  8529.     switch(m_nGlobalDetail)
  8530.     {
  8531.         case    DETAIL_LOW:
  8532.             pClientDE->ReadConfigFile("detaillo.cfg");
  8533.             break;
  8534.         case    DETAIL_MEDIUM:
  8535.             pClientDE->ReadConfigFile("detailmd.cfg");
  8536.             break;
  8537.         case    DETAIL_HIGH:
  8538.             pClientDE->ReadConfigFile("detailhi.cfg");
  8539.             break;
  8540.     }
  8541.  
  8542.     // record the original state of sound and music
  8543.  
  8544.     hVar = pClientDE->GetConsoleVar ("SoundEnable");
  8545.     m_bSoundOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar);
  8546.     
  8547.     hVar = pClientDE->GetConsoleVar ("MusicEnable");
  8548.     m_bMusicOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar);
  8549.  
  8550.     hVar = pClientDE->GetConsoleVar ("ModelFullbrite");
  8551.     m_bModelFBOriginallyEnabled    = (DBOOL) pClientDE->GetVarValueFloat (hVar);
  8552.     
  8553.     hVar = pClientDE->GetConsoleVar ("LightMap");
  8554.     m_bLightmappingOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar);
  8555.  
  8556.     // implement any advanced options here (before renderer is started)
  8557.  
  8558.     hVar = pClientDE->GetConsoleVar ("SoundEnable");
  8559.     if (!hVar && !AdvancedDisableSound())
  8560.     {
  8561.         pClientDE->RunConsoleString ("SoundEnable 1");
  8562.     }
  8563.     else if (AdvancedDisableSound())
  8564.     {
  8565.         pClientDE->RunConsoleString ("SoundEnable 0");    // [blg] is this ok?
  8566.     }
  8567.  
  8568.     hVar = pClientDE->GetConsoleVar ("MusicEnable");
  8569.     if (!hVar && !AdvancedDisableMusic())
  8570.     {
  8571.         pClientDE->RunConsoleString ("MusicEnable 1");
  8572.     }
  8573.     else if (AdvancedDisableMusic())
  8574.     {
  8575.         pClientDE->RunConsoleString ("MusicEnable 0");    // [blg] is this ok?
  8576.     }
  8577.  
  8578.     if (AdvancedDisableLightMap())
  8579.     {
  8580.         pClientDE->RunConsoleString ("LightMap 0");
  8581.     }
  8582.     if (AdvancedEnableOptSurf())
  8583.     {
  8584.         pClientDE->RunConsoleString ("OptimizeSurfaces 1");
  8585.     }
  8586.     if (AdvancedEnableTripBuf())
  8587.     {
  8588.         pClientDE->RunConsoleString ("TripleBuffer 1");
  8589.     }
  8590.     if (AdvancedDisableDx6Cmds())
  8591.     {
  8592.         pClientDE->RunConsoleString ("UseDX6Commands 0");
  8593.     }
  8594.     if (AdvancedEnableTJuncs())
  8595.     {
  8596.         pClientDE->RunConsoleString ("FixTJunc 1");
  8597.     }
  8598.     if (AdvancedDisableFog())
  8599.     {
  8600.         pClientDE->RunConsoleString ("FogEnable 0");
  8601.     }
  8602.     if (AdvancedDisableLines())
  8603.     {
  8604.         pClientDE->RunConsoleString ("DrawLineSystems 0");
  8605.     }
  8606.     if (AdvancedDisableModelFB())
  8607.     {
  8608.         pClientDE->RunConsoleString ("ModelFullBrite 0");
  8609.     }
  8610.     if (AdvancedDisableJoystick())
  8611.     {
  8612.         pClientDE->RunConsoleString ("JoystickDisable 1");
  8613.     }
  8614.     if (AdvancedEnablePixelDoubling())
  8615.     {
  8616.         pClientDE->RunConsoleString ("PixelDouble 1");
  8617.     }
  8618.     if (AdvancedEnableMultiTexturing())
  8619.     {
  8620.         pClientDE->RunConsoleString ("Force1Pass 1");
  8621.     }
  8622.  
  8623.     return DTRUE;
  8624. }
  8625. // ----------------------------------------------------------------------- //
  8626. //
  8627. //    ROUTINE:    CBloodClientShell::HandleInvAction()
  8628. //
  8629. //    PURPOSE:    The player has hit an exit trigger.
  8630. //
  8631. // ----------------------------------------------------------------------- //
  8632.  
  8633. void CBloodClientShell::HandleInvAction( DBYTE nType, DBOOL bActivate )
  8634. {
  8635.     switch( nType )
  8636.     {
  8637.         case INV_BINOCULARS:
  8638.             PlaySoundLocal( "sounds\\powerups\\binoculars.wav", SOUNDPRIORITY_PLAYER_LOW );
  8639.             m_bBinocularsActive = bActivate;
  8640.             break;
  8641.         case INV_MEDKIT:
  8642.             PlaySoundLocal( "sounds\\powerups\\medikit.wav", SOUNDPRIORITY_PLAYER_LOW );
  8643.             break;
  8644.         case INV_FLASHLIGHT:
  8645.             PlaySoundLocal( "sounds\\powerups\\flashlight.wav", SOUNDPRIORITY_PLAYER_LOW );
  8646.             break;
  8647.         case INV_NIGHTGOGGLES:
  8648.             m_bNightGogglesActive = bActivate;
  8649.             break;
  8650.         default:
  8651.             break;
  8652.     }
  8653. }
  8654.  
  8655. // ----------------------------------------------------------------------- //
  8656. //
  8657. //    ROUTINE:    CBloodClientShell::SetMouseSensitivity()
  8658. //
  8659. //    PURPOSE:    Sets the mouse sensitivity
  8660. //
  8661. // ----------------------------------------------------------------------- //
  8662.  
  8663. void CBloodClientShell::SetMouseSensitivity(float fSensitivity)
  8664. {
  8665.     CClientDE *pClientDE=GetClientDE();
  8666.     if (!pClientDE)
  8667.     {
  8668.         return;
  8669.     }
  8670.  
  8671.     char szDeviceName[256];
  8672.     char szXAxis[256];
  8673.     char szYAxis[256];
  8674.  
  8675.     memset(szDeviceName, 0, sizeof(szDeviceName));
  8676.     memset(szXAxis, 0, sizeof(szXAxis));
  8677.     memset(szYAxis, 0, sizeof(szYAxis));
  8678.  
  8679.     // Get the mouse device information
  8680.     GetMouseDeviceInfo(szDeviceName, sizeof(szDeviceName), szXAxis, sizeof(szXAxis), szYAxis, sizeof(szYAxis));
  8681.  
  8682.     if (_mbstrlen(szDeviceName) == 0)
  8683.     {
  8684.         return;
  8685.     }
  8686.  
  8687.     // Run the console strings
  8688.     char strConsole[256];
  8689.  
  8690.     if (_mbstrlen(szXAxis) > 0)
  8691.     {
  8692.         sprintf (strConsole, "scale \"%s\" \"%s\" %f", szDeviceName, szXAxis, 0.00125f + (fSensitivity * 0.001125f));
  8693.         pClientDE->RunConsoleString (strConsole);
  8694.     }
  8695.  
  8696.     if (_mbstrlen(szYAxis) > 0)
  8697.     {
  8698.         sprintf (strConsole, "scale \"%s\" \"%s\" %f", szDeviceName, szYAxis, 0.00125f + (fSensitivity * 0.001125f));
  8699.         pClientDE->RunConsoleString (strConsole);
  8700.     }
  8701.  
  8702.     sprintf(strConsole, "MouseSensitivity %f", fSensitivity);
  8703.     pClientDE->RunConsoleString(strConsole);
  8704. }
  8705.  
  8706. // ----------------------------------------------------------------------- //
  8707. //
  8708. //    ROUTINE:    CBloodClientShell::GetMouseDeviceInfo()
  8709. //
  8710. //    PURPOSE:    Get the mouse device name and axis names
  8711. //
  8712. // ----------------------------------------------------------------------- //
  8713.  
  8714. void CBloodClientShell::GetMouseDeviceInfo(char *lpszDeviceName, int nDeviceBufferSize,
  8715.                                            char *lpszXAxis,         int nXAxisBufferSize,
  8716.                                            char *lpszYAxis,         int nYAxisBufferSize)
  8717. {
  8718.     // Most of this code was taken from Shogo...
  8719.     CClientDE *pClientDE=GetClientDE();
  8720.     if (!pClientDE)
  8721.     {
  8722.         return;
  8723.     }
  8724.  
  8725.     // get the mouse device name    
  8726.     DRESULT result = pClientDE->GetDeviceName (DEVICETYPE_MOUSE, lpszDeviceName, nDeviceBufferSize);
  8727.     if (result == LT_OK)
  8728.     {        
  8729.         DeviceObject* pList = pClientDE->GetDeviceObjects (DEVICETYPE_MOUSE);
  8730.         DeviceObject* ptr = pList;
  8731.         while (ptr)
  8732.         {
  8733.             if (ptr->m_ObjectType == CONTROLTYPE_XAXIS)
  8734.             {
  8735.                 _mbsncpy((unsigned char*)lpszXAxis, (const unsigned char*)ptr->m_ObjectName, nXAxisBufferSize);                
  8736.             }
  8737.  
  8738.             if (ptr->m_ObjectType == CONTROLTYPE_YAXIS)
  8739.             {
  8740.                 _mbsncpy((unsigned char*)lpszYAxis, (const unsigned char*)ptr->m_ObjectName, nYAxisBufferSize);                
  8741.             }
  8742.  
  8743.             ptr = ptr->m_pNext;
  8744.         }
  8745.         if (pList)
  8746.         {
  8747.             pClientDE->FreeDeviceObjects (pList);        
  8748.         }
  8749.     }
  8750. }
  8751.  
  8752. // ----------------------------------------------------------------------- //
  8753. //
  8754. //    ROUTINE:    CBloodClientShell::GetMouseSensitivity()
  8755. //
  8756. //    PURPOSE:    Gets the mouse sensitivity
  8757. //
  8758. // ----------------------------------------------------------------------- //
  8759.  
  8760. float CBloodClientShell::GetMouseSensitivity()
  8761. {
  8762.     CClientDE *pClientDE=GetClientDE();
  8763.     if (!pClientDE)
  8764.     {
  8765.         return 1.5f;
  8766.     }
  8767.  
  8768.     // Load the mouse sensitivity
  8769.     HCONSOLEVAR hVar=pClientDE->GetConsoleVar("MouseSensitivity");
  8770.     if (hVar)
  8771.     {
  8772.         return pClientDE->GetVarValueFloat(hVar);
  8773.     }
  8774.     else
  8775.     {
  8776.         return 1.5f;
  8777.     }
  8778. }
  8779.  
  8780. // ----------------------------------------------------------------------- //
  8781. //
  8782. //    ROUTINE:    CBloodClientShell::SetUseJoystick()
  8783. //
  8784. //    PURPOSE:    Turns the "UseJoystick" console variable on and off
  8785. //
  8786. // ----------------------------------------------------------------------- //
  8787.  
  8788. void CBloodClientShell::SetUseJoystick(DBOOL bUseJoystick)
  8789. {
  8790.     m_bUseJoystick=bUseJoystick;
  8791.  
  8792.     CClientDE *pClientDE=GetClientDE();
  8793.     if (!pClientDE)
  8794.     {
  8795.         return;
  8796.     }
  8797.  
  8798.     if (m_bUseJoystick)
  8799.     {
  8800.         pClientDE->RunConsoleString("+usejoystick 1");        // probably don't need this, should remove and just use joystickdisable everywhere!
  8801.         pClientDE->RunConsoleString("+joystickdisable 0");  // the engine looks at this one
  8802.     }
  8803.     else
  8804.     {
  8805.         pClientDE->RunConsoleString("+usejoystick 0");        // probably don't need this, should remove and just use joystickdisable everywhere!
  8806.         pClientDE->RunConsoleString("+joystickdisable 1");  // the engine looks at this one
  8807.     }
  8808. }
  8809.  
  8810. // ----------------------------------------------------------------------- //
  8811. //
  8812. //    ROUTINE:    CBloodClientShell::SetKeyboardTurnRate()
  8813. //
  8814. //    PURPOSE:    Sets the keyboard turn rate
  8815. //
  8816. // ----------------------------------------------------------------------- //
  8817.  
  8818. void CBloodClientShell::SetKeyboardTurnRate(float fRate)
  8819. {
  8820.     m_fKeyboardTurnRate=fRate;
  8821.  
  8822.     CClientDE *pClientDE=GetClientDE();
  8823.     if (!pClientDE)
  8824.     {
  8825.         return;
  8826.     }
  8827.     
  8828.     char szTemp[256];
  8829.     sprintf(szTemp, "+KeyboardTurnRate %f", m_fKeyboardTurnRate);
  8830.     pClientDE->RunConsoleString(szTemp);
  8831. }
  8832.  
  8833.  
  8834. // ----------------------------------------------------------------------- //
  8835. //
  8836. //    ROUTINE:    CBloodClientShell::DoMessageBox()
  8837. //
  8838. //    PURPOSE:    Puts a message box on the screen.  It is removed when ENTER, ESC,
  8839. //                or SPACE is pressed or on the next page flip if bAsync is FALSE.
  8840. //
  8841. // ----------------------------------------------------------------------- //
  8842. void CBloodClientShell::DoMessageBox(char *lpszMessage, DBOOL bAsync)
  8843. {    
  8844.     // TODO: Make this localizable
  8845.     ClientDE *pClientDE=GetClientDE();
  8846.  
  8847.     HSTRING hString=pClientDE->CreateString(lpszMessage);
  8848.     m_messageBox.SetText(hString);    
  8849.     pClientDE->FreeString(hString);
  8850.  
  8851.     m_messageBox.SetCommandHandler(&m_messageBoxHandler);
  8852.  
  8853.     m_messageBox.RemoveKeys();
  8854.     m_messageBox.AddKey(VK_ESCAPE, MESSAGE_BOX_ID_KILL);
  8855.     m_messageBox.AddKey(VK_RETURN, MESSAGE_BOX_ID_KILL);
  8856.     m_messageBox.AddKey(VK_SPACE, MESSAGE_BOX_ID_KILL);
  8857.  
  8858.     m_bInMessageBox=DTRUE;
  8859.  
  8860.     if (!bAsync)
  8861.     {
  8862.         // Render the message box to the screen
  8863.         PostUpdate();
  8864.         PostUpdate();
  8865.         m_bInMessageBox=DFALSE;
  8866.     }
  8867. }
  8868.  
  8869.  
  8870. // ----------------------------------------------------------------------- //
  8871. //
  8872. //    ROUTINE:    CBloodClientShell::KillMessageBox()
  8873. //
  8874. //    PURPOSE:    Kills the message box
  8875. //
  8876. // ----------------------------------------------------------------------- //
  8877. void CBloodClientShell::KillMessageBox()
  8878. {
  8879.     m_bInMessageBox=DFALSE;
  8880. }
  8881.  
  8882. // ----------------------------------------------------------------------- //
  8883. //
  8884. //    ROUTINE:    CBloodClientShell::ShowInfoBox
  8885. //
  8886. //    PURPOSE:    Displays an informational message box.
  8887. //    Params:        lpszMessage:  The message to be displayed
  8888. //                bAddOkButton: TRUE if the box should have an OK button to close
  8889. //
  8890. // ----------------------------------------------------------------------- //
  8891.  
  8892. void CBloodClientShell::ShowInfoBox(char *lpszMessage, DBOOL bAddOkButton)
  8893. {
  8894.     if (!lpszMessage) return;
  8895.  
  8896.     CSPrint(lpszMessage);
  8897. }
  8898.  
  8899.  
  8900. // ----------------------------------------------------------------------- //
  8901. //
  8902. //    ROUTINE:    CBloodClientShell::KillInfoBox
  8903. //
  8904. //    PURPOSE:    Stops the display of any info message box.
  8905. //
  8906. // ----------------------------------------------------------------------- //
  8907.  
  8908. void CBloodClientShell::KillInfoBox()
  8909. {
  8910. }
  8911.  
  8912.  
  8913.  
  8914. // --------------------------------------------------------------------------- //
  8915. //
  8916. //    ROUTINE:    CBloodClientShell::HandleFiring()
  8917. //
  8918. //    PURPOSE:    Checks for firing commands and updates the weapon object
  8919. //
  8920. // --------------------------------------------------------------------------- //
  8921. DBOOL CBloodClientShell::HandleFiring()
  8922. {
  8923.     ClientDE *pClientDE=GetClientDE();
  8924.  
  8925.     DRotation rotGun;
  8926.     DVector vRGunPos, vLGunPos, vMyPos;
  8927.  
  8928.     HLOCALOBJ hPlayerObj = pClientDE->GetClientObject();
  8929.     pClientDE->GetObjectPos(hPlayerObj, &vMyPos);
  8930.  
  8931.     VEC_ADD(vRGunPos, vMyPos, cdata.GunMuzzlePos);
  8932.     VEC_ADD(vLGunPos, vMyPos, cdata.lGunMuzzlePos);
  8933.  
  8934.     ROT_COPY(rotGun, m_Rotation);
  8935.  
  8936.     if (!m_bDead && !m_bSpectatorMode)
  8937.     {
  8938.         DBOOL bFiring = DFALSE;
  8939.         DBOOL bAltFiring = DFALSE;
  8940.  
  8941.         if (cdata.byFlags & CDATA_CANMOVE)
  8942.         {
  8943.             bFiring = (m_pMoveMgr->GetControlFlags() & CTRLFLAG_FIRE) != 0;
  8944.             bAltFiring = (!bFiring && (m_pMoveMgr->GetControlFlags() & CTRLFLAG_ALTFIRE));
  8945.         }
  8946.  
  8947.         // If we have duel weapons, make the altfire the same as the primary
  8948.         if (m_pWeapon && m_pLWeapon && bAltFiring)
  8949.             { bFiring = DTRUE; bAltFiring = DFALSE; }
  8950.  
  8951.         if (m_pWeapon)
  8952.             m_pWeapon->UpdateFiringState(&vRGunPos, &rotGun, bFiring, bAltFiring);
  8953.  
  8954.         if (m_pLWeapon)
  8955.             m_pLWeapon->UpdateFiringState(&vLGunPos, &rotGun, bFiring, bAltFiring);
  8956.     }
  8957.     else if (m_bDead)
  8958.     {
  8959.         if (m_pWeapon)        m_pWeapon->CancelFiringState();
  8960.         if (m_pLWeapon)        m_pLWeapon->CancelFiringState();
  8961.  
  8962. /*        if (m_pWeapon)
  8963.             m_pWeapon->UpdateFiringState(&vRGunPos, &rotGun, DFALSE, DFALSE);
  8964.  
  8965.         if (m_pLWeapon)
  8966.             m_pLWeapon->UpdateFiringState(&vLGunPos, &rotGun, DFALSE, DFALSE);
  8967. */    }
  8968.  
  8969.     return DTRUE;
  8970. }
  8971.  
  8972.  
  8973. // --------------------------------------------------------------------------- //
  8974. //
  8975. //    ROUTINE:    CBloodClientShell::CreateWeapon()
  8976. //
  8977. //    PURPOSE:    Creates a view weapon model.
  8978. //
  8979. // --------------------------------------------------------------------------- //
  8980. CViewWeapon* CBloodClientShell::CreateWeapon(DBYTE byType, DBOOL bLeftHand)
  8981. {
  8982.     ClientDE *pClientDE = GetClientDE();
  8983.     CViewWeapon *w = DNULL;
  8984.  
  8985.     switch (byType)
  8986.     {
  8987.         case WEAP_BERETTA:
  8988.             w = new CBeretta;
  8989.             break;
  8990.  
  8991.         case WEAP_SHOTGUN:
  8992.             w = new CShotgun;
  8993.             break;
  8994.  
  8995.         case WEAP_SNIPERRIFLE:
  8996.             w = new CSniperRifle;
  8997.             break;
  8998.  
  8999.         case WEAP_ASSAULTRIFLE:
  9000.             w = new CAssaultRifle;
  9001.             break;
  9002.  
  9003.         case WEAP_SUBMACHINEGUN:
  9004.             w = new CSubMachineGun;
  9005.             break;
  9006.  
  9007.         case WEAP_FLAREGUN:
  9008.             w = new CFlareGun;
  9009.             break;
  9010.  
  9011.         case WEAP_HOWITZER:
  9012.             w = new CHowitzer;
  9013.             break;
  9014.  
  9015.         case WEAP_BUGSPRAY:
  9016.             w = new CBugSpray;
  9017.             break;
  9018.  
  9019.         case WEAP_NAPALMCANNON:
  9020.             w = new CNapalmCannon;
  9021.             break;
  9022.  
  9023.         case WEAP_MINIGUN:
  9024.             w = new CMiniGun;
  9025.             break;
  9026.  
  9027.         case WEAP_VOODOO:
  9028.             w = new CVoodooDoll;
  9029.             break;
  9030.  
  9031.         case WEAP_ORB:
  9032.             w = new COrb;
  9033.             break;
  9034.  
  9035.         case WEAP_DEATHRAY:
  9036.             w = new CDeathRay;
  9037.             break;
  9038.  
  9039.         case WEAP_LIFELEECH:
  9040.             w = new CLifeLeech;
  9041.             break;
  9042.  
  9043.         case WEAP_TESLACANNON:
  9044.             w = new CTeslaCannon;
  9045.             break;
  9046.  
  9047.         case WEAP_SINGULARITY:
  9048.             w = new CSingularity;
  9049.             break;
  9050.  
  9051.         case WEAP_MELEE:
  9052.             w = new CMelee;
  9053.             break;
  9054.  
  9055. #ifdef _ADD_ON
  9056.  
  9057.         case WEAP_COMBATSHOTGUN:
  9058.             w = new CCombatShotgun;
  9059.             break;
  9060.  
  9061.         case WEAP_FLAYER:
  9062.             w = new CFlayer;
  9063.             break;
  9064. #endif
  9065.  
  9066. #ifndef _DEMO
  9067.         case WEAP_PROXIMITYBOMB:
  9068.             w = new CWeapProximityBomb;
  9069.             break;
  9070.  
  9071.         case WEAP_REMOTEBOMB:
  9072.             w = new CWeapRemoteBomb;
  9073.             break;
  9074.  
  9075.         case WEAP_TIMEBOMB:
  9076.             w = new CWeapTimeBomb;
  9077.             break;
  9078. #endif
  9079.     }
  9080.  
  9081.     if (w)
  9082.         w->Create(pClientDE, byType, bLeftHand);
  9083.  
  9084.     return w;
  9085. }
  9086.  
  9087.  
  9088. // --------------------------------------------------------------------------- //
  9089. //
  9090. //    ROUTINE:    CBloodClientShell::CreateWeapon()
  9091. //
  9092. //    PURPOSE:    Creates a view weapon model.
  9093. //
  9094. // --------------------------------------------------------------------------- //
  9095. void CBloodClientShell::SetPowerBarLevel(DFLOAT fPercent)
  9096. {
  9097.     ClientDE *pClientDE = GetClientDE();
  9098.  
  9099.     if((fPercent <= 0.0f) || (fPercent >= 1.0f))
  9100.         m_NewStatusBar.TurnOffPowerBar();
  9101.     else
  9102.         m_NewStatusBar.SetPowerBarLevel(BARTAB_THROW, fPercent);
  9103. }
  9104.  
  9105.  
  9106. // --------------------------------------------------------------------------- //
  9107. //
  9108. //    ROUTINE:    CBloodClientShell::PlaySound
  9109. //
  9110. //    PURPOSE:    Plays the given sound
  9111. //
  9112. // --------------------------------------------------------------------------- //
  9113.  
  9114. HSOUNDDE CBloodClientShell::PlaySound(char* sSound, DBOOL bStream, DBOOL bLoop, DBOOL bGetHandle)
  9115. {
  9116.     // Sanity checks...
  9117.  
  9118.     if (!g_pClientDE) return(NULL);
  9119.  
  9120.  
  9121.     // Fill out the structure...
  9122.  
  9123.     PlaySoundInfo playSoundInfo;
  9124.  
  9125.     PLAYSOUNDINFO_INIT(playSoundInfo);
  9126.     playSoundInfo.m_dwFlags = PLAYSOUND_LOCAL;
  9127.  
  9128.     if (bStream)
  9129.     {
  9130.         playSoundInfo.m_dwFlags |= PLAYSOUND_FILESTREAM;
  9131.     }
  9132.     if (bLoop)
  9133.     {
  9134.         playSoundInfo.m_dwFlags |= PLAYSOUND_LOOP;
  9135.     }
  9136.     if (bGetHandle)
  9137.     {
  9138.         playSoundInfo.m_dwFlags |= PLAYSOUND_GETHANDLE;
  9139.     }
  9140.  
  9141.     _mbsncpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)sSound, sizeof(playSoundInfo.m_szSoundName) - 1);
  9142.  
  9143.     playSoundInfo.m_nPriority = SOUNDPRIORITY_MISC_MEDIUM;
  9144.  
  9145.  
  9146.     // Play the sound...
  9147.  
  9148.     if(g_pClientDE->PlaySound(&playSoundInfo) != LT_OK )
  9149.         return NULL;
  9150.     
  9151.     return playSoundInfo.m_hSound;
  9152. }
  9153.  
  9154. // --------------------------------------------------------------------------- //
  9155. //
  9156. //    ROUTINE:    CBloodClientShell::DisplayStatusBarFlagIcon
  9157. //
  9158. //    PURPOSE:    Controls the display of the status bar flag icon
  9159. //
  9160. // --------------------------------------------------------------------------- //
  9161.  
  9162. void CBloodClientShell::DisplayStatusBarFlagIcon(DBOOL bDisplay)
  9163. {
  9164.     // Check if we should turn if off...
  9165.  
  9166.     if (!bDisplay)
  9167.     {
  9168.         m_NewStatusBar.DisplayFlag(MULTIFLAG_NONE);
  9169.         return;
  9170.     }
  9171.  
  9172.  
  9173.     // Figure out which team we're on...
  9174.  
  9175.     if (!g_pClientDE) return;
  9176.  
  9177.     DDWORD dwLocalID = 0;
  9178.     g_pClientDE->GetLocalClientID(&dwLocalID);
  9179.  
  9180.     CTeam* pTeam = m_TeamMgr.GetTeamFromPlayerID(dwLocalID);
  9181.     if (!pTeam) return;
  9182.  
  9183.     BYTE byFlagType = MULTIFLAG_NONE;
  9184.  
  9185.     if (pTeam->GetID() == TEAM_1) byFlagType = MULTIFLAG_RED;    // show the other teams flag!
  9186.     if (pTeam->GetID() == TEAM_2) byFlagType = MULTIFLAG_BLUE;
  9187.  
  9188.     m_NewStatusBar.DisplayFlag(byFlagType);
  9189. }
  9190.  
  9191.  
  9192. // --------------------------------------------------------------------------- //
  9193. //
  9194. //    ROUTINE:    CBloodClientShell::AssignFrags
  9195. //
  9196. //    PURPOSE:    Assigns frags as necessary based on the game options
  9197. //
  9198. // --------------------------------------------------------------------------- //
  9199.  
  9200. void CBloodClientShell::AssignFrags(DDWORD dwLocalID, DDWORD dwVictim, DDWORD dwKiller)
  9201. {
  9202.     if (dwVictim == dwKiller)
  9203.     {
  9204.         m_FragInfo.RemoveFrag(dwLocalID, dwKiller);
  9205.         m_TeamMgr.AddPlayerFrags(dwKiller, -1);
  9206.     }
  9207.     else
  9208.     {
  9209.         if (IsMultiplayerTeamBasedGame())
  9210.         {
  9211.             if (!m_TeamMgr.IsOnSameTeam(dwKiller, dwVictim))    // not on same team
  9212.             {
  9213.                 if (!IsNetOnlyFlagScores() && !IsNetOnlyGoalScores())
  9214.                 {
  9215.                     m_FragInfo.AddFrag(dwLocalID, dwKiller);
  9216.                     m_TeamMgr.AddPlayerFrags(dwKiller, +1);
  9217.                 }
  9218.             }
  9219.             else    // on the same team
  9220.             {
  9221.                 if (IsNetFriendlyFire() && IsNetNegTeamFrags())
  9222.                 {
  9223.                     m_FragInfo.RemoveFrag(dwLocalID, dwKiller);
  9224.                     m_TeamMgr.AddPlayerFrags(dwKiller, -1);
  9225.                 }
  9226.             }
  9227.         }
  9228.         else
  9229.         {
  9230.             m_FragInfo.AddFrag(dwLocalID, dwKiller);
  9231.         }
  9232.     }
  9233. }
  9234.  
  9235.  
  9236. // --------------------------------------------------------------------------- //
  9237. //
  9238. //    ROUTINE:    CBloodClientShell::StartWonkyVision
  9239. //
  9240. //    PURPOSE:    Turns on wonky vision
  9241. //
  9242. // --------------------------------------------------------------------------- //
  9243.  
  9244. void CBloodClientShell::StartWonkyVision(DFLOAT fWonkyTime, DBOOL bWonkyNoMove)
  9245. {
  9246.     if (fWonkyTime == 0) return;
  9247.  
  9248.     m_fWonkyTime   = fWonkyTime;
  9249.     m_bWonkyVision = DTRUE;
  9250.     m_bWonkyNoMove = bWonkyNoMove;
  9251. }
  9252.  
  9253.  
  9254. // --------------------------------------------------------------------------- //
  9255. //
  9256. //    ROUTINE:    CBloodClientShell::EndWonkyVision
  9257. //
  9258. //    PURPOSE:    Turns off wonky vision
  9259. //
  9260. // --------------------------------------------------------------------------- //
  9261.  
  9262. void CBloodClientShell::EndWonkyVision()
  9263. {
  9264.     m_fWonkyTime   = 0;
  9265.     m_bWonkyVision = DFALSE;
  9266.     m_bWonkyNoMove = DFALSE;
  9267. }
  9268.  
  9269.  
  9270. // --------------------------------------------------------------------------- //
  9271. //
  9272. //    ROUTINE:    CBloodClientShell::SetCharacterInfo
  9273. //
  9274. //    PURPOSE:    Sets the character info for the given character
  9275. //
  9276. // --------------------------------------------------------------------------- //
  9277.  
  9278. DBOOL CBloodClientShell::SetCharacterInfo(int nCharacter, int nSkin)
  9279. {
  9280.     m_Config.nCharacter = nCharacter;
  9281.     m_Config.nSkin      = nSkin;
  9282.  
  9283.     switch (m_Config.nCharacter)
  9284.     {
  9285.         case CHARACTER_CALEB:
  9286.         {
  9287.             m_Config.nStrength   = 5;
  9288.             m_Config.nSpeed      = 3;
  9289.             m_Config.nResistance = 3;
  9290.             m_Config.nMagic      = 1;
  9291.             break;
  9292.         }
  9293.  
  9294.         case CHARACTER_OPHELIA:
  9295.         {
  9296.             m_Config.nStrength   = 2;
  9297.             m_Config.nSpeed      = 5;
  9298.             m_Config.nResistance = 1;
  9299.             m_Config.nMagic      = 4;
  9300.             break;
  9301.         }
  9302.  
  9303.         case CHARACTER_ISHMAEL:
  9304.         {
  9305.             m_Config.nStrength   = 1;
  9306.             m_Config.nSpeed      = 3;
  9307.             m_Config.nResistance = 3;
  9308.             m_Config.nMagic      = 5;
  9309.             break;
  9310.         }
  9311.  
  9312.         case CHARACTER_GABREILLA:
  9313.         {
  9314.             m_Config.nStrength   = 5;
  9315.             m_Config.nSpeed      = 1;
  9316.             m_Config.nResistance = 5;
  9317.             m_Config.nMagic      = 1;
  9318.             break;
  9319.         }
  9320.  
  9321. #ifdef _ADDON
  9322.         case CHARACTER_M_CULTIST:
  9323.         {
  9324.             m_Config.nStrength   = 5;
  9325.             m_Config.nSpeed      = 3;
  9326.             m_Config.nResistance = 3;
  9327.             m_Config.nMagic      = 1;
  9328.             break;
  9329.         }
  9330.  
  9331.         case CHARACTER_F_CULTIST:
  9332.         {
  9333.             m_Config.nStrength   = 2;
  9334.             m_Config.nSpeed      = 5;
  9335.             m_Config.nResistance = 1;
  9336.             m_Config.nMagic      = 4;
  9337.             break;
  9338.         }
  9339.  
  9340.         case CHARACTER_SOULDRUDGE:
  9341.         {
  9342.             m_Config.nStrength   = 1;
  9343.             m_Config.nSpeed      = 3;
  9344.             m_Config.nResistance = 3;
  9345.             m_Config.nMagic      = 5;
  9346.             break;
  9347.         }
  9348.  
  9349.         case CHARACTER_PROPHET:
  9350.         {
  9351.             m_Config.nStrength   = 5;
  9352.             m_Config.nSpeed      = 1;
  9353.             m_Config.nResistance = 5;
  9354.             m_Config.nMagic      = 1;
  9355.             break;
  9356.         }
  9357. #endif
  9358.  
  9359.         default: return(DFALSE);
  9360.     }
  9361.  
  9362.  
  9363.     // All done...
  9364.  
  9365.     return(DTRUE);
  9366. }
  9367.  
  9368. // --------------------------------------------------------------------------- //
  9369. //
  9370. //    ROUTINE:    CBloodClientShell::ResetPlayerInventory
  9371. //
  9372. //    PURPOSE:    
  9373. //
  9374. // --------------------------------------------------------------------------- //
  9375.  
  9376. void CBloodClientShell::ResetPlayerInventory()
  9377. {
  9378.     ClientDE *pClientDE=GetClientDE();
  9379.  
  9380.     // Clear the weapon info
  9381.     for (int i=0;i<CLIENTWEAPONSLOTS;i++)
  9382.     {
  9383.         m_abyWeaponID[i]    = WEAP_NONE;
  9384.         m_abyLWeaponID[i]    = WEAP_NONE;
  9385.     }
  9386.  
  9387.     // Delete the current viewmodels
  9388.     if(m_pWeapon)
  9389.     {
  9390.         delete m_pWeapon;
  9391.         m_pWeapon = DNULL;
  9392.     }
  9393.  
  9394.     if(m_pLWeapon)
  9395.     {
  9396.         delete m_pLWeapon;
  9397.         m_pLWeapon = DNULL;
  9398.     }
  9399.  
  9400.     // Reset the in game interface stuff
  9401.     m_NewStatusBar.Reset();
  9402.  
  9403.     // Send a message to the PlayerObj on the server to clear everything
  9404.     HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_RESETPLAYERINVENTORY);
  9405.     pClientDE->EndMessage(hMessage);
  9406. }